1- // mruby-simplemsgpack C++ packer wrapper (msgpack::packer + msgpack::sbuffer)
21#define MSGPACK_NO_BOOST
32#define MSGPACK_DEFAULT_API_VERSION 3
43#include < msgpack.hpp>
@@ -68,6 +67,37 @@ static inline void mrb_msgpack_pack_string_value(mrb_state *mrb, mrb_value self,
6867 }
6968}
7069
70+ #ifdef MRB_MSGPACK_SYMBOLS
71+
72+ #ifndef MRB_MSGPACK_SYMBOLS_EXT
73+ #define MRB_MSGPACK_SYMBOLS_EXT 1
74+ #endif
75+
76+ template <typename Packer>
77+ static inline void
78+ mrb_msgpack_pack_symbol_value (mrb_state* mrb, mrb_value self, Packer& pk)
79+ {
80+ mrb_sym sym = mrb_symbol (self);
81+
82+ #ifdef MRB_MSGPACK_SYMBOLS_AS_INT
83+ // Pack the raw mrb_sym value as the ext body
84+ pk.pack_ext (sizeof (sym), static_cast <int8_t >(MRB_MSGPACK_SYMBOLS_EXT));
85+ pk.pack_ext_body (reinterpret_cast <const char *>(&sym), sizeof (sym));
86+
87+ #else
88+ // Pack the symbol’s name as the ext body, using mrb_sym_name_len
89+ mrb_int len;
90+ const char * name = mrb_sym_name_len (mrb, sym, &len);
91+
92+ pk.pack_ext (static_cast <uint32_t >(len),
93+ static_cast <int8_t >(MRB_MSGPACK_SYMBOLS_EXT));
94+ pk.pack_ext_body (name, static_cast <size_t >(len));
95+
96+ #endif
97+ }
98+
99+ #endif // MRB_MSGPACK_SYMBOLS
100+
71101template <typename Packer>
72102static void mrb_msgpack_pack_array_value (mrb_state* mrb, mrb_value self, Packer& pk) {
73103 mrb_int n = RARRAY_LEN (self);
@@ -197,6 +227,11 @@ static void mrb_msgpack_pack_value(mrb_state* mrb, mrb_value self, Packer& pk) {
197227 case MRB_TT_STRING:
198228 mrb_msgpack_pack_string_value (mrb, self, pk);
199229 break ;
230+ #ifdef MRB_MSGPACK_SYMBOLS
231+ case MRB_TT_SYMBOL:
232+ mrb_msgpack_pack_symbol_value (mrb, self, pk);
233+ break ;
234+ #endif
200235 default : {
201236 if (mrb_msgpack_pack_ext_value (mrb, self, pk)) break ;
202237
@@ -250,6 +285,27 @@ mrb_msgpack_pack_string(mrb_state* mrb, mrb_value self) {
250285 return mrb_nil_value ();
251286}
252287
288+ #ifdef MRB_MSGPACK_SYMBOLS
289+
290+ static mrb_value
291+ mrb_msgpack_pack_symbol (mrb_state* mrb, mrb_value self) {
292+ try {
293+ msgpack::sbuffer sbuf;
294+ msgpack::packer<msgpack::sbuffer> pk (&sbuf);
295+ mrb_msgpack_pack_symbol_value (mrb, self, pk);
296+ return mrb_str_new (mrb, sbuf.data (), sbuf.size ());
297+ } catch (const std::bad_alloc&) {
298+ mrb_exc_raise (mrb, mrb_obj_value (mrb->nomem_err ));
299+ } catch (const std::exception& e) {
300+ mrb_raisef (mrb, E_MSGPACK_ERROR,
301+ " cannot pack symbol: %S" ,
302+ mrb_str_new_cstr (mrb, e.what ()));
303+ }
304+ return mrb_nil_value ();
305+ }
306+
307+ #endif // MRB_MSGPACK_SYMBOLS
308+
253309static mrb_value
254310mrb_msgpack_pack_array (mrb_state* mrb, mrb_value self) {
255311 try {
@@ -420,6 +476,13 @@ mrb_msgpack_register_pack_type(mrb_state* mrb, mrb_value self)
420476 mrb_raise (mrb, E_TYPE_ERROR, " not a block" );
421477 }
422478
479+ #ifdef MRB_MSGPACK_SYMBOLS
480+ // Prevent registering ext packers for Symbol when built-in symbol packing is enabled
481+ if (mrb_class_ptr (mrb_class) == mrb->symbol_class ) {
482+ mrb_raise (mrb, E_ARGUMENT_ERROR, " cannot register ext packer for Symbol when MRB_MSGPACK_SYMBOLS is enabled" );
483+ }
484+ #endif
485+
423486 ext_packers = mrb_const_get (mrb, self, MRB_SYM (_ExtPackers));
424487 ext_config = mrb_hash_new_capa (mrb, 2 );
425488 mrb_hash_set (mrb, ext_config, mrb_symbol_value (MRB_SYM (type)), mrb_int_value (mrb, type));
@@ -476,7 +539,25 @@ mrb_unpack_msgpack_obj(mrb_state* mrb, const msgpack::object& obj)
476539 return mrb_unpack_msgpack_obj_map (mrb, obj);
477540 case msgpack::type::EXT: {
478541 auto ext_type = obj.via .ext .type ();
479-
542+ #ifdef MRB_MSGPACK_SYMBOLS
543+ if (ext_type == MRB_MSGPACK_SYMBOLS_EXT) {
544+ # ifdef MRB_MSGPACK_SYMBOLS_AS_INT
545+ // Body is a raw mrb_sym
546+ if (unlikely (obj.via .ext .size != sizeof (mrb_sym))) {
547+ mrb_raise (mrb, E_MSGPACK_ERROR, " invalid symbol ext body size" );
548+ }
549+ mrb_sym sym;
550+ std::memcpy (&sym, obj.via .ext .data (), sizeof (sym));
551+ return mrb_symbol_value (sym);
552+ # else
553+ // Body is the UTF‑8 symbol name
554+ return mrb_symbol_value (
555+ mrb_intern (mrb,
556+ obj.via .ext .data (),
557+ (size_t )obj.via .ext .size ));
558+ # endif
559+ }
560+ #endif // MRB_MSGPACK_SYMBOLS
480561 mrb_value unpacker = mrb_hash_get (mrb,
481562 mrb_const_get (mrb, mrb_obj_value (mrb_module_get_id (mrb, MRB_SYM (MessagePack))), MRB_SYM (_ExtUnpackers)),
482563 mrb_int_value (mrb, ext_type));
@@ -733,6 +814,14 @@ mrb_msgpack_register_unpack_type(mrb_state* mrb, mrb_value self)
733814 mrb_raise (mrb, E_TYPE_ERROR, " not a block" );
734815 }
735816
817+ #ifdef MRB_MSGPACK_SYMBOLS
818+ /* Prevent registering an unpacker for the reserved symbol ext type */
819+ if (type == MRB_MSGPACK_SYMBOLS_EXT) {
820+ mrb_raise (mrb, E_ARGUMENT_ERROR,
821+ " cannot register unpacker for Symbol ext type when MRB_MSGPACK_SYMBOLS is enabled" );
822+ }
823+ #endif
824+
736825 mrb_hash_set (mrb, mrb_const_get (mrb, self, MRB_SYM (_ExtUnpackers)), mrb_int_value (mrb, type), block);
737826
738827 return mrb_nil_value ();
@@ -751,40 +840,45 @@ MRB_BEGIN_DECL
751840void
752841mrb_mruby_simplemsgpack_gem_init (mrb_state* mrb)
753842{
754- struct RClass * msgpack_mod, *mrb_object_handle_class;
843+ struct RClass * msgpack_mod, *mrb_object_handle_class;
755844
756- mrb_define_method (mrb, mrb->object_class , " to_msgpack" , mrb_msgpack_pack_object, MRB_ARGS_NONE ());
757- mrb_define_method (mrb, mrb->string_class , " to_msgpack" , mrb_msgpack_pack_string, MRB_ARGS_NONE ());
758- mrb_define_method (mrb, mrb->array_class , " to_msgpack" , mrb_msgpack_pack_array, MRB_ARGS_NONE ());
759- mrb_define_method (mrb, mrb->hash_class , " to_msgpack" , mrb_msgpack_pack_hash, MRB_ARGS_NONE ());
845+ mrb_define_method_id (mrb, mrb->object_class , MRB_SYM (to_msgpack), mrb_msgpack_pack_object, MRB_ARGS_NONE ());
846+ mrb_define_method_id (mrb, mrb->string_class , MRB_SYM (to_msgpack), mrb_msgpack_pack_string, MRB_ARGS_NONE ());
847+ #ifdef MRB_MSGPACK_SYMBOLS
848+ mrb_define_method_id (mrb, mrb->symbol_class , MRB_SYM (to_msgpack), mrb_msgpack_pack_symbol, MRB_ARGS_NONE ());
849+ #endif
850+ mrb_define_method_id (mrb, mrb->array_class , MRB_SYM (to_msgpack), mrb_msgpack_pack_array, MRB_ARGS_NONE ());
851+ mrb_define_method_id (mrb, mrb->hash_class , MRB_SYM (to_msgpack), mrb_msgpack_pack_hash, MRB_ARGS_NONE ());
760852#ifndef MRB_WITHOUT_FLOAT
761- mrb_define_method (mrb, mrb->float_class , " to_msgpack" , mrb_msgpack_pack_float, MRB_ARGS_NONE ());
853+ mrb_define_method_id (mrb, mrb->float_class , MRB_SYM ( to_msgpack) , mrb_msgpack_pack_float, MRB_ARGS_NONE ());
762854#endif
763- mrb_define_method (mrb, mrb->integer_class , " to_msgpack" , mrb_msgpack_pack_integer, MRB_ARGS_NONE ());
764- mrb_define_method (mrb, mrb->true_class , " to_msgpack" , mrb_msgpack_pack_true, MRB_ARGS_NONE ());
765- mrb_define_method (mrb, mrb->false_class , " to_msgpack" , mrb_msgpack_pack_false, MRB_ARGS_NONE ());
766- mrb_define_method (mrb, mrb->nil_class , " to_msgpack" , mrb_msgpack_pack_nil, MRB_ARGS_NONE ());
767- msgpack_mod = mrb_define_module (mrb, " MessagePack" );
768- mrb_define_class_under (mrb, msgpack_mod, " Error" , E_RUNTIME_ERROR);
769- mrb_object_handle_class = mrb_define_class_under (mrb, msgpack_mod, " ObjectHandle" , mrb->object_class );
770- MRB_SET_INSTANCE_TT (mrb_object_handle_class, MRB_TT_DATA);
771- mrb_define_method (mrb, mrb_object_handle_class, " initialize" , mrb_msgpack_object_handle_new, MRB_ARGS_REQ (1 ));
772- mrb_define_method (mrb, mrb_object_handle_class, " value" , mrb_msgpack_object_handle_value, MRB_ARGS_NONE ());
773- mrb_define_method (mrb, mrb_object_handle_class, " at_pointer" , mrb_msgpack_object_handle_at_pointer, MRB_ARGS_REQ (1 ));
774-
775-
776- mrb_define_const (mrb, msgpack_mod, " LibMsgPackCVersion" , mrb_str_new_lit (mrb, MSGPACK_VERSION));
777- mrb_define_const (mrb, msgpack_mod, " _ExtPackers" , mrb_hash_new (mrb));
778- mrb_define_const (mrb, msgpack_mod, " _ExtUnpackers" , mrb_hash_new (mrb));
779-
780- mrb_define_module_function (mrb, msgpack_mod, " pack" , mrb_msgpack_pack_m, MRB_ARGS_REQ (1 ));
781- mrb_define_module_function (mrb, msgpack_mod, " register_pack_type" , mrb_msgpack_register_pack_type, (MRB_ARGS_REQ (2 )|MRB_ARGS_BLOCK ()));
782- mrb_define_module_function (mrb, msgpack_mod, " ext_packer_registered?" , mrb_msgpack_ext_packer_registered, MRB_ARGS_REQ (1 ));
783- mrb_define_module_function (mrb, msgpack_mod, " unpack" , mrb_msgpack_unpack_m, (MRB_ARGS_REQ (1 )|MRB_ARGS_BLOCK ()));
784- mrb_define_module_function (mrb, msgpack_mod, " unpack_lazy" , mrb_msgpack_unpack_lazy_m, (MRB_ARGS_REQ (1 )));
785- mrb_define_module_function (mrb, msgpack_mod, " register_unpack_type" , mrb_msgpack_register_unpack_type, (MRB_ARGS_REQ (1 )|MRB_ARGS_BLOCK ()));
786- mrb_define_module_function (mrb, msgpack_mod, " ext_unpacker_registered?" , mrb_msgpack_ext_unpacker_registered, MRB_ARGS_REQ (1 ));
787- }
788-
789- void mrb_mruby_simplemsgpack_gem_final (mrb_state* mrb) {}
790- MRB_END_DECL
855+ mrb_define_method_id (mrb, mrb->integer_class , MRB_SYM (to_msgpack), mrb_msgpack_pack_integer, MRB_ARGS_NONE ());
856+ mrb_define_method_id (mrb, mrb->true_class , MRB_SYM (to_msgpack), mrb_msgpack_pack_true, MRB_ARGS_NONE ());
857+ mrb_define_method_id (mrb, mrb->false_class , MRB_SYM (to_msgpack), mrb_msgpack_pack_false, MRB_ARGS_NONE ());
858+ mrb_define_method_id (mrb, mrb->nil_class , MRB_SYM (to_msgpack), mrb_msgpack_pack_nil, MRB_ARGS_NONE ());
859+
860+ msgpack_mod = mrb_define_module_id (mrb, MRB_SYM (MessagePack));
861+ mrb_define_class_under_id (mrb, msgpack_mod, MRB_SYM (Error), E_RUNTIME_ERROR);
862+
863+ mrb_object_handle_class = mrb_define_class_under_id (mrb, msgpack_mod, MRB_SYM (ObjectHandle), mrb->object_class );
864+ MRB_SET_INSTANCE_TT (mrb_object_handle_class, MRB_TT_DATA);
865+ mrb_define_method_id (mrb, mrb_object_handle_class, MRB_SYM (initialize), mrb_msgpack_object_handle_new, MRB_ARGS_REQ (1 ));
866+ mrb_define_method_id (mrb, mrb_object_handle_class, MRB_SYM (value), mrb_msgpack_object_handle_value, MRB_ARGS_NONE ());
867+ mrb_define_method_id (mrb, mrb_object_handle_class, MRB_SYM (at_pointer), mrb_msgpack_object_handle_at_pointer, MRB_ARGS_REQ (1 ));
868+
869+ mrb_define_const_id (mrb, msgpack_mod, MRB_SYM (LibMsgPackCVersion), mrb_str_new_lit (mrb, MSGPACK_VERSION));
870+ mrb_define_const_id (mrb, msgpack_mod, MRB_SYM (_ExtPackers), mrb_hash_new (mrb));
871+ mrb_define_const_id (mrb, msgpack_mod, MRB_SYM (_ExtUnpackers), mrb_hash_new (mrb));
872+
873+ mrb_define_module_function_id (mrb, msgpack_mod, MRB_SYM (pack), mrb_msgpack_pack_m, MRB_ARGS_REQ (1 ));
874+ mrb_define_module_function_id (mrb, msgpack_mod, MRB_SYM (register_pack_type), mrb_msgpack_register_pack_type, (MRB_ARGS_REQ (2 )|MRB_ARGS_BLOCK ()));
875+ mrb_define_module_function_id (mrb, msgpack_mod, MRB_SYM_Q (ext_packer_registered), mrb_msgpack_ext_packer_registered, MRB_ARGS_REQ (1 ));
876+ mrb_define_module_function_id (mrb, msgpack_mod, MRB_SYM (unpack), mrb_msgpack_unpack_m, (MRB_ARGS_REQ (1 )|MRB_ARGS_BLOCK ()));
877+ mrb_define_module_function_id (mrb, msgpack_mod, MRB_SYM (unpack_lazy), mrb_msgpack_unpack_lazy_m, MRB_ARGS_REQ (1 ));
878+ mrb_define_module_function_id (mrb, msgpack_mod, MRB_SYM (register_unpack_type), mrb_msgpack_register_unpack_type, (MRB_ARGS_REQ (1 )|MRB_ARGS_BLOCK ()));
879+ mrb_define_module_function_id (mrb, msgpack_mod, MRB_SYM_Q (ext_unpacker_registered), mrb_msgpack_ext_unpacker_registered, MRB_ARGS_REQ (1 ));
880+ }
881+
882+ void
883+ mrb_mruby_simplemsgpack_gem_final (mrb_state* mrb) {}
884+ MRB_END_DECL
0 commit comments