3 * MessagePack serializer
5 * MessagePack is a space-efficient binary data interchange format. This
6 * class provides a pack() method that encodes native PHP values as MessagePack
7 * binary strings. The implementation is derived from msgpack-php.
9 * Copyright (c) 2013 Ori Livneh <ori@wikimedia.org>
10 * Copyright (c) 2011 OnlineCity <https://github.com/onlinecity/msgpack-php>.
12 * Permission is hereby granted, free of charge, to any person obtaining a copy
13 * of this software and associated documentation files (the "Software"), to
14 * deal in the Software without restriction, including without limitation the
15 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16 * sell copies of the Software, and to permit persons to whom the Software is
17 * furnished to do so, subject to the following conditions:
19 * The above copyright notice and this permission notice shall be included in
20 * all copies or substantial portions of the Software.
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
29 * @see <http://msgpack.org/>
30 * @see <http://wiki.msgpack.org/display/MSGPACK/Format+specification>
34 * @deprecated since 1.34, no longer used
37 /** @var bool|null Whether current system is bigendian. */
38 public static $bigendian = null;
41 * Encode a value using MessagePack
43 * This method supports null, boolean, integer, float, string and array
44 * (both indexed and associative) types. Object serialization is not
47 * @deprecated since 1.34, no longer used
51 * @throws InvalidArgumentException if $value is an unsupported type or too long a string
53 public static function pack( $value ) {
54 wfDeprecated( __METHOD__
, '1.34' );
55 if ( self
::$bigendian === null ) {
56 self
::$bigendian = pack( 'S', 1 ) === pack( 'n', 1 );
59 switch ( gettype( $value ) ) {
64 return $value ?
"\xC3" : "\xC2";
68 return self
::$bigendian
69 ?
"\xCB" . pack( 'd', $value )
70 : "\xCB" . strrev( pack( 'd', $value ) );
73 $length = strlen( $value );
75 return pack( 'Ca*', 0xA0 |
$length, $value );
76 } elseif ( $length <= 0xFFFF ) {
77 return pack( 'Cna*', 0xDA, $length, $value );
78 } elseif ( $length <= 0xFFFFFFFF ) {
79 return pack( 'CNa*', 0xDB, $length, $value );
81 throw new InvalidArgumentException( __METHOD__
82 . ": string too long (length: $length; max: 4294967295)" );
86 if ( $value <= 0x7F ) {
90 if ( $value <= 0xFF ) {
92 return pack( 'CC', 0xCC, $value );
94 if ( $value <= 0xFFFF ) {
96 return pack( 'Cn', 0xCD, $value );
98 if ( $value <= 0xFFFFFFFF ) {
100 return pack( 'CN', 0xCE, $value );
102 if ( $value <= 0xFFFFFFFFFFFFFFFF ) {
104 $hi = ( $value & 0xFFFFFFFF00000000 ) >> 32;
105 $lo = $value & 0xFFFFFFFF;
106 return self
::$bigendian
107 ?
pack( 'CNN', 0xCF, $lo, $hi )
108 : pack( 'CNN', 0xCF, $hi, $lo );
111 if ( $value >= -32 ) {
113 return pack( 'c', $value );
115 if ( $value >= -0x80 ) {
117 return pack( 'Cc', 0xD0, $value );
119 if ( $value >= -0x8000 ) {
121 $p = pack( 's', $value );
122 return self
::$bigendian
123 ?
pack( 'Ca2', 0xD1, $p )
124 : pack( 'Ca2', 0xD1, strrev( $p ) );
126 if ( $value >= -0x80000000 ) {
128 $p = pack( 'l', $value );
129 return self
::$bigendian
130 ?
pack( 'Ca4', 0xD2, $p )
131 : pack( 'Ca4', 0xD2, strrev( $p ) );
133 if ( $value >= -0x8000000000000000 ) {
135 // pack() does not support 64-bit ints either so pack into two 32-bits
136 $p1 = pack( 'l', $value & 0xFFFFFFFF );
137 // @phan-suppress-next-line PhanTypeInvalidLeftOperandOfIntegerOp
138 $p2 = pack( 'l', ( $value >> 32 ) & 0xFFFFFFFF );
139 return self
::$bigendian
140 ?
pack( 'Ca4a4', 0xD3, $p1, $p2 )
141 : pack( 'Ca4a4', 0xD3, strrev( $p2 ), strrev( $p1 ) );
144 throw new InvalidArgumentException( __METHOD__
. ": invalid integer '$value'" );
148 $length = count( $value );
149 if ( $length > 0xFFFFFFFF ) {
150 throw new InvalidArgumentException( __METHOD__
151 . ": array too long (length: $length, max: 4294967295)" );
155 foreach ( $value as $k => $v ) {
156 if ( $index !== $k ||
$index === $length ) {
162 $associative = $index !== $length;
164 if ( $associative ) {
165 if ( $length < 16 ) {
166 $buffer .= pack( 'C', 0x80 |
$length );
167 } elseif ( $length <= 0xFFFF ) {
168 $buffer .= pack( 'Cn', 0xDE, $length );
170 $buffer .= pack( 'CN', 0xDF, $length );
172 foreach ( $value as $k => $v ) {
173 $buffer .= self
::pack( $k );
174 $buffer .= self
::pack( $v );
177 if ( $length < 16 ) {
178 $buffer .= pack( 'C', 0x90 |
$length );
179 } elseif ( $length <= 0xFFFF ) {
180 $buffer .= pack( 'Cn', 0xDC, $length );
182 $buffer .= pack( 'CN', 0xDD, $length );
184 foreach ( $value as $v ) {
185 $buffer .= self
::pack( $v );
191 throw new InvalidArgumentException( __METHOD__
. ': unsupported type ' . gettype( $value ) );