Skip to content

Commit

Permalink
#171 Add serialization and deserialization support for PHP 8.1 Enums.
Browse files Browse the repository at this point in the history
  • Loading branch information
seyfahni authored and m6w6 committed Aug 19, 2024
1 parent 2f792ff commit 93fe730
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 0 deletions.
17 changes: 17 additions & 0 deletions msgpack_pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
#include "ext/standard/php_incomplete_class.h"
#include "ext/standard/php_var.h"

#if PHP_VERSION_ID >= 80100
#include "Zend/zend_enum.h"
#endif

#include "php_msgpack.h"
#include "msgpack_pack.h"
#include "msgpack_errors.h"
Expand Down Expand Up @@ -408,6 +412,19 @@ static inline void msgpack_serialize_object(smart_str *buf, zval *val, HashTable
PHP_CLEANUP_CLASS_ATTRIBUTES();
return;
}
if (ce && (ce->ce_flags & ZEND_ACC_ENUM)) {
zval *enum_case_name = zend_enum_fetch_case_name(Z_OBJ_P(val_noref));
msgpack_pack_map(buf, 2);

msgpack_pack_nil(buf);
msgpack_pack_long(buf, MSGPACK_SERIALIZE_TYPE_ENUM);

msgpack_serialize_string(buf, ZSTR_VAL(ce->name), ZSTR_LEN(ce->name));
msgpack_serialize_string(buf, Z_STRVAL_P(enum_case_name), Z_STRLEN_P(enum_case_name));

PHP_CLEANUP_CLASS_ATTRIBUTES();
return;
}
#endif

#if PHP_VERSION_ID >= 70400
Expand Down
1 change: 1 addition & 0 deletions msgpack_pack.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ enum msgpack_serialize_type
MSGPACK_SERIALIZE_TYPE_CUSTOM_OBJECT,
MSGPACK_SERIALIZE_TYPE_OBJECT,
MSGPACK_SERIALIZE_TYPE_OBJECT_REFERENCE,
MSGPACK_SERIALIZE_TYPE_ENUM,
};

void msgpack_serialize_var_init(msgpack_serialize_data_t *var_hash);
Expand Down
25 changes: 25 additions & 0 deletions msgpack_unpack.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
#include "php_ini.h"
#include "ext/standard/php_incomplete_class.h"

#if PHP_VERSION_ID >= 80100
#include "Zend/zend_enum.h"
#endif

#include "php_msgpack.h"
#include "msgpack_pack.h"
#include "msgpack_unpack.h"
Expand Down Expand Up @@ -617,6 +621,7 @@ int msgpack_unserialize_map_item(msgpack_unpack_data *unpack, zval **container,
case MSGPACK_SERIALIZE_TYPE_CUSTOM_OBJECT:
case MSGPACK_SERIALIZE_TYPE_OBJECT_REFERENCE:
case MSGPACK_SERIALIZE_TYPE_OBJECT:
case MSGPACK_SERIALIZE_TYPE_ENUM:
unpack->type = Z_LVAL_P(val);
break;
default:
Expand Down Expand Up @@ -674,6 +679,26 @@ int msgpack_unserialize_map_item(msgpack_unpack_data *unpack, zval **container,
return 0;
}

case MSGPACK_SERIALIZE_TYPE_ENUM:
{
if (Z_TYPE_P(key) != IS_STRING) {
MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val);
return MSGPACK_UNPACK_PARSE_ERROR;
}

#if PHP_VERSION_ID < 80100
MSGPACK_WARNING(
"[msgpack] (%s) Class %s is an Enum and not supported below PHP 8.1",
__FUNCTION__, Z_STRVAL_P(key));
#else
ce = msgpack_unserialize_class(container, Z_STR_P(key), 0);
zend_object *enum_instance = zend_enum_get_case(ce, Z_STR_P(val));
ZVAL_OBJ(*container, enum_instance);
#endif
MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val);
return 0;
}

case MSGPACK_SERIALIZE_TYPE_RECURSIVE:
case MSGPACK_SERIALIZE_TYPE_OBJECT:
case MSGPACK_SERIALIZE_TYPE_OBJECT_REFERENCE:
Expand Down
31 changes: 31 additions & 0 deletions tests/issue171.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
--TEST--
Issue #171 (Serializing & Unserializing Enum)
--SKIPIF--
<?php
if (!extension_loaded("msgpack")) {
exit('skip because msgpack extension is missing');
}
if (version_compare(PHP_VERSION, '8.1.0', '<')) {
exit('skip Enum tests in PHP older than 8.1.0');
}
?>
--FILE--
Test
<?php
enum TestEnum {
case EITHER;
case OTHER;
}

$packed = msgpack_pack(TestEnum::OTHER);
var_dump(bin2hex($packed));

$unpacked = msgpack_unpack($packed);
var_dump($unpacked);
?>
OK
--EXPECT--
Test
string(36) "82c006a854657374456e756da54f54484552"
enum(TestEnum::OTHER)
OK

0 comments on commit 93fe730

Please sign in to comment.