Passed
Branch test (3b2ced)
by Josh
01:57
created

Encoder::encodeObject()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 5
nc 3
nop 1
dl 0
loc 12
ccs 6
cts 6
cp 1
crap 3
rs 10
c 1
b 0
f 0
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
{
17 20
	public static function encode($value): string
18
	{
19 20
		if (is_string($value))
20
		{
21 2
			return strlen($value) . ':' . $value;
22
		}
23 20
		if (is_array($value))
24
		{
25 7
			return self::encodeArray($value);
26
		}
27 17
		if (is_int($value))
28
		{
29 12
			return "i{$value}e";
30
		}
31 10
		if (is_object($value))
32
		{
33 5
			return self::encodeObject($value);
34
		}
35
36 5
		return self::encode(self::coerceUnsupportedValue($value));
37
	}
38
39 7
	protected static function arrayIsList(array $array): bool
40
	{
41 7
		$expectedKey = 0;
42 7
		foreach ($array as $k => $v)
43
		{
44 6
			if ($k !== $expectedKey)
45
			{
46 6
				return false;
47
			}
48 2
			++$expectedKey;
49
		}
50
51 3
		return true;
52
	}
53
54 2
	protected static function coerceBool(bool $value): int
55
	{
56 2
		return (int) $value;
57
	}
58
59 2
	protected static function coerceFloat(float $value): int
60
	{
61 2
		$int = (int) $value;
62 2
		if ((float) $int === $value)
63
		{
64 1
			return $int;
65
		}
66
67 1
		throw new EncodingException('Unsupported value', $value);
68
	}
69
70 5
	protected static function coerceUnsupportedValue($value): array|int|string
71
	{
72 5
		if (is_float($value))
73
		{
74 2
			return self::coerceFloat($value);
75
		}
76 3
		if (is_bool($value))
77
		{
78 2
			return self::coerceBool($value);
79
		}
80
81 1
		throw new EncodingException('Unsupported value', $value);
82
	}
83
84
	/**
85
	* Encode a PHP array into either a list of a dictionary
86
	*/
87 7
	protected static function encodeArray(array $value): string
88
	{
89 7
		return self::arrayIsList($value)
90 3
			? self::encodeIndexedArray($value)
91 7
			: self::encodeAssociativeArray($value);
92
	}
93
94 10
	protected static function encodeAssociativeArray(array $array): string
95
	{
96 10
		ksort($array, SORT_STRING);
97
98 10
		$str = 'd';
99 10
		foreach ($array as $k => $v)
100
		{
101 8
			$str .= strlen((string) $k) . ':' . $k . self::encode($v);
102
		}
103 10
		$str .= 'e';
104
105 10
		return $str;
106
	}
107
108 3
	protected static function encodeIndexedArray(array $array): string
109
	{
110 3
		$str = 'l';
111 3
		foreach ($array as $v)
112
		{
113 2
			$str .= self::encode($v);
114
		}
115 3
		$str .= 'e';
116
117 3
		return $str;
118
	}
119
120 5
	protected static function encodeObject(object $value): string
121
	{
122 5
		if ($value instanceof ArrayObject)
123
		{
124 1
			return self::encodeAssociativeArray($value->getArrayCopy());
125
		}
126 4
		if ($value instanceof stdClass)
127
		{
128 3
			return self::encodeAssociativeArray(get_object_vars($value));
129
		}
130
131 1
		throw new EncodingException('Unsupported value', $value);
132
	}
133
}