| 1 |  |  | <?php declare(strict_types=1); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  | /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 |  |  | * @package   s9e\Bencode | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  | * @copyright Copyright (c) 2014-2021 The s9e authors | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 |  |  | * @license   http://www.opensource.org/licenses/mit-license.php The MIT License | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 |  |  | */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 |  |  | namespace s9e\Bencode; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 |  |  | use ArrayObject; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 11 |  |  | use function get_object_vars, is_array, is_bool, is_float, is_int, is_object, is_string, ksort, strlen; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 12 |  |  | use s9e\Bencode\Exceptions\EncodingException; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  | use stdClass; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 |  |  | class Encoder | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 | 16 |  | { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  | 	public static function encode($value): string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 | 16 |  | 	{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 19 | 16 |  | 		if (is_string($value)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 20 |  |  | 		{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 | 15 |  | 			return strlen($value) . ':' . $value; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 22 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 |  |  | 		if (is_array($value)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 | 1 |  | 		{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 25 |  |  | 			return self::encodeArray($value); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 27 |  |  | 		if (is_int($value)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 28 |  |  | 		{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 |  |  | 			return "i{$value}e"; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 | 5 |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 |  |  | 		if (is_object($value)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 32 | 5 |  | 		{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 33 |  |  | 			return self::encodeObject($value); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 34 | 1 |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 35 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 36 |  |  | 		return self::encode(self::coerceUnsupportedValue($value)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 37 | 4 |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 38 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 39 | 2 |  | 	protected static function arrayIsList(array $array): bool | 
            
                                                                                                            
                            
            
                                    
            
            
                | 40 |  |  | 	{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 41 |  |  | 		$expectedKey = 0; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 42 |  |  | 		foreach ($array as $k => $v) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 43 | 4 |  | 		{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 44 |  |  | 			if ($k !== $expectedKey) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 45 |  |  | 			{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 46 | 7 |  | 				return false; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 47 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 48 | 7 |  | 			++$expectedKey; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 49 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 50 | 7 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 51 | 7 |  | 		return true; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 | 6 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 |  |  | 	protected static function coerceBool(bool $value): int | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 | 7 |  | 	{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 |  |  | 		return (int) $value; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 | 7 |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 59 |  |  | 	protected static function coerceFloat(float $value): int | 
            
                                                                                                            
                            
            
                                    
            
            
                | 60 | 2 |  | 	{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 61 |  |  | 		$int = (int) $value; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 62 | 2 |  | 		if ((float) $int === $value) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 63 |  |  | 		{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 64 |  |  | 			return $int; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 65 | 2 |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 66 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 67 | 2 |  | 		throw new EncodingException('Unsupported value', $value); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 | 2 |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 70 | 1 |  | 	protected static function coerceUnsupportedValue($value): array|int|string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 |  |  | 	{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 |  |  | 		if (is_float($value)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 | 1 |  | 		{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 |  |  | 			return self::coerceFloat($value); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 | 5 |  | 		if (is_bool($value)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 77 |  |  | 		{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 78 | 5 |  | 			return self::coerceBool($value); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 79 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 80 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 | 2 |  | 		throw new EncodingException('Unsupported value', $value); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 | 2 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 |  |  | 	* Encode a PHP array into either a list of a dictionary | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 | 9 |  | 	*/ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 |  |  | 	protected static function encodeArray(array $value): string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 | 9 |  | 	{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 |  |  | 		return self::arrayIsList($value) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 |  |  | 			? self::encodeIndexedArray($value) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 | 4 |  | 			: self::encodeAssociativeArray($value); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 |  |  | 	} | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 93 | 4 |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 94 | 4 |  | 	protected static function encodeAssociativeArray(array $array): string | 
            
                                                                        
                            
            
                                    
            
            
                | 95 | 4 |  | 	{ | 
            
                                                                        
                            
            
                                    
            
            
                | 96 |  |  | 		ksort($array, SORT_STRING); | 
            
                                                                        
                            
            
                                    
            
            
                | 97 | 3 |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 98 |  |  | 		$str = 'd'; | 
            
                                                                        
                            
            
                                    
            
            
                | 99 |  |  | 		foreach ($array as $k => $v) | 
            
                                                                        
                            
            
                                    
            
            
                | 100 | 1 |  | 		{ | 
            
                                                                        
                            
            
                                    
            
            
                | 101 |  |  | 			$str .= strlen((string) $k) . ':' . $k . self::encode($v); | 
            
                                                                        
                            
            
                                    
            
            
                | 102 |  |  | 		} | 
            
                                                                        
                            
            
                                    
            
            
                | 103 | 2 |  | 		$str .= 'e'; | 
            
                                                                        
                            
            
                                    
            
            
                | 104 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 105 | 2 |  | 		return $str; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 106 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 107 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 108 |  |  | 	protected static function encodeIndexedArray(array $array): string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 109 |  |  | 	{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 110 |  |  | 		$str = 'l'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 111 |  |  | 		foreach ($array as $v) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 112 |  |  | 		{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 113 |  |  | 			$str .= self::encode($v); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 114 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 115 |  |  | 		$str .= 'e'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 116 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 117 |  |  | 		return $str; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 118 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 119 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 120 |  |  | 	protected static function encodeObject(object $value): string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 121 |  |  | 	{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 122 |  |  | 		if ($value instanceof ArrayObject) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 123 |  |  | 		{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 124 |  |  | 			return self::encodeAssociativeArray($value->getArrayCopy()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 125 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 126 |  |  | 		if ($value instanceof stdClass) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 127 |  |  | 		{ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 128 |  |  | 			return self::encodeAssociativeArray(get_object_vars($value)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 129 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 130 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 131 |  |  | 		throw new EncodingException('Unsupported value', $value); | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 132 |  |  | 	} | 
            
                                                        
            
                                    
            
            
                | 133 |  |  | } |