Skip to content

Commit 93fe730

Browse files
seyfahnim6w6
authored andcommitted
#171 Add serialization and deserialization support for PHP 8.1 Enums.
1 parent 2f792ff commit 93fe730

File tree

4 files changed

+74
-0
lines changed

4 files changed

+74
-0
lines changed

msgpack_pack.c

+17
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
#include "ext/standard/php_incomplete_class.h"
77
#include "ext/standard/php_var.h"
88

9+
#if PHP_VERSION_ID >= 80100
10+
#include "Zend/zend_enum.h"
11+
#endif
12+
913
#include "php_msgpack.h"
1014
#include "msgpack_pack.h"
1115
#include "msgpack_errors.h"
@@ -408,6 +412,19 @@ static inline void msgpack_serialize_object(smart_str *buf, zval *val, HashTable
408412
PHP_CLEANUP_CLASS_ATTRIBUTES();
409413
return;
410414
}
415+
if (ce && (ce->ce_flags & ZEND_ACC_ENUM)) {
416+
zval *enum_case_name = zend_enum_fetch_case_name(Z_OBJ_P(val_noref));
417+
msgpack_pack_map(buf, 2);
418+
419+
msgpack_pack_nil(buf);
420+
msgpack_pack_long(buf, MSGPACK_SERIALIZE_TYPE_ENUM);
421+
422+
msgpack_serialize_string(buf, ZSTR_VAL(ce->name), ZSTR_LEN(ce->name));
423+
msgpack_serialize_string(buf, Z_STRVAL_P(enum_case_name), Z_STRLEN_P(enum_case_name));
424+
425+
PHP_CLEANUP_CLASS_ATTRIBUTES();
426+
return;
427+
}
411428
#endif
412429

413430
#if PHP_VERSION_ID >= 70400

msgpack_pack.h

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ enum msgpack_serialize_type
1919
MSGPACK_SERIALIZE_TYPE_CUSTOM_OBJECT,
2020
MSGPACK_SERIALIZE_TYPE_OBJECT,
2121
MSGPACK_SERIALIZE_TYPE_OBJECT_REFERENCE,
22+
MSGPACK_SERIALIZE_TYPE_ENUM,
2223
};
2324

2425
void msgpack_serialize_var_init(msgpack_serialize_data_t *var_hash);

msgpack_unpack.c

+25
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
#include "php_ini.h"
33
#include "ext/standard/php_incomplete_class.h"
44

5+
#if PHP_VERSION_ID >= 80100
6+
#include "Zend/zend_enum.h"
7+
#endif
8+
59
#include "php_msgpack.h"
610
#include "msgpack_pack.h"
711
#include "msgpack_unpack.h"
@@ -617,6 +621,7 @@ int msgpack_unserialize_map_item(msgpack_unpack_data *unpack, zval **container,
617621
case MSGPACK_SERIALIZE_TYPE_CUSTOM_OBJECT:
618622
case MSGPACK_SERIALIZE_TYPE_OBJECT_REFERENCE:
619623
case MSGPACK_SERIALIZE_TYPE_OBJECT:
624+
case MSGPACK_SERIALIZE_TYPE_ENUM:
620625
unpack->type = Z_LVAL_P(val);
621626
break;
622627
default:
@@ -674,6 +679,26 @@ int msgpack_unserialize_map_item(msgpack_unpack_data *unpack, zval **container,
674679
return 0;
675680
}
676681

682+
case MSGPACK_SERIALIZE_TYPE_ENUM:
683+
{
684+
if (Z_TYPE_P(key) != IS_STRING) {
685+
MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val);
686+
return MSGPACK_UNPACK_PARSE_ERROR;
687+
}
688+
689+
#if PHP_VERSION_ID < 80100
690+
MSGPACK_WARNING(
691+
"[msgpack] (%s) Class %s is an Enum and not supported below PHP 8.1",
692+
__FUNCTION__, Z_STRVAL_P(key));
693+
#else
694+
ce = msgpack_unserialize_class(container, Z_STR_P(key), 0);
695+
zend_object *enum_instance = zend_enum_get_case(ce, Z_STR_P(val));
696+
ZVAL_OBJ(*container, enum_instance);
697+
#endif
698+
MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val);
699+
return 0;
700+
}
701+
677702
case MSGPACK_SERIALIZE_TYPE_RECURSIVE:
678703
case MSGPACK_SERIALIZE_TYPE_OBJECT:
679704
case MSGPACK_SERIALIZE_TYPE_OBJECT_REFERENCE:

tests/issue171.phpt

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
--TEST--
2+
Issue #171 (Serializing & Unserializing Enum)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded("msgpack")) {
6+
exit('skip because msgpack extension is missing');
7+
}
8+
if (version_compare(PHP_VERSION, '8.1.0', '<')) {
9+
exit('skip Enum tests in PHP older than 8.1.0');
10+
}
11+
?>
12+
--FILE--
13+
Test
14+
<?php
15+
enum TestEnum {
16+
case EITHER;
17+
case OTHER;
18+
}
19+
20+
$packed = msgpack_pack(TestEnum::OTHER);
21+
var_dump(bin2hex($packed));
22+
23+
$unpacked = msgpack_unpack($packed);
24+
var_dump($unpacked);
25+
?>
26+
OK
27+
--EXPECT--
28+
Test
29+
string(36) "82c006a854657374456e756da54f54484552"
30+
enum(TestEnum::OTHER)
31+
OK

0 commit comments

Comments
 (0)