Passed
Branch master (52a373)
by Josh
02:08
created

Encoder::arrayIsList()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 6
c 0
b 0
f 0
nc 3
nop 1
dl 0
loc 13
rs 10
ccs 6
cts 6
cp 1
crap 3
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
}