Skip to content

Commit dda1f94

Browse files
committed
encode and decode classes
1 parent 88857c7 commit dda1f94

2 files changed

Lines changed: 36 additions & 0 deletions

File tree

mrbgem.rake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ MRuby::Gem::Specification.new('mruby-cbor') do |spec|
1010
spec.add_dependency 'mruby-time'
1111
spec.add_dependency 'mruby-string-is-utf8'
1212
spec.add_dependency 'mruby-native-ext-type', github: 'Asmod4n/mruby-native-ext-type', branch: 'main'
13+
spec.add_dependency 'mruby-str-constantize', github: 'Asmod4n/mruby-str-constantize', branch: 'main'
1314
spec.add_test_dependency 'mruby-bigint'
1415
spec.add_test_dependency 'mruby-random'
1516
spec.add_test_dependency 'mruby-io'

src/mrb_cbor.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ MRB_END_DECL
1414
#include <mruby/variable.h>
1515
#include <mruby/error.h>
1616
#include <mruby/ned.h>
17+
#include <mruby/str_constantize.h>
1718

1819
#include <stdlib.h>
1920
#include <stdint.h>
@@ -33,6 +34,8 @@ MRB_END_DECL
3334
#endif
3435
#endif
3536

37+
#define CBOR_TAG_CLASS UINT32_C(49999)
38+
3639
typedef struct {
3740
const uint8_t* base;
3841
const uint8_t* p;
@@ -627,6 +630,16 @@ decode_symbol(mrb_state *mrb, Reader* r, mrb_value src, mrb_value sharedrefs)
627630
return mrb_nil_value();
628631
}
629632

633+
static mrb_value
634+
decode_class(mrb_state *mrb, Reader *r, mrb_value src, mrb_value sharedrefs)
635+
{
636+
mrb_value v = decode_value(mrb, r, src, sharedrefs);
637+
if (likely(mrb_string_p(v)))
638+
return mrb_str_constantize(mrb, v);
639+
mrb_raise(mrb, E_TYPE_ERROR, "invalid payload for tag 49999 (expected text string)");
640+
return mrb_undef_value();
641+
}
642+
630643
// ============================================================================
631644
// Master decode with depth protection
632645
// ============================================================================
@@ -673,6 +686,10 @@ decode_value(mrb_state* mrb, Reader* r, mrb_value src, mrb_value sharedrefs)
673686
result = decode_symbol(mrb, r, src, sharedrefs);
674687
goto done;
675688
}
689+
if (mrb_integer_p(tag) && (uint64_t)mrb_integer(tag) == CBOR_TAG_CLASS) {
690+
result = decode_class(mrb, r, src, sharedrefs);
691+
goto done;
692+
}
676693

677694
{
678695
mrb_value reg = cbor_tag_registry(mrb);
@@ -999,6 +1016,20 @@ encode_string(CborWriter* w, mrb_value str)
9991016
cbor_writer_write(w, (const uint8_t*)p, (size_t)blen);
10001017
}
10011018

1019+
static void
1020+
encode_class(CborWriter *w, mrb_value obj)
1021+
{
1022+
mrb_state *mrb = w->mrb;
1023+
mrb_value name = mrb_class_path(mrb, mrb_class_ptr(obj));
1024+
1025+
if (likely(mrb_string_p(name))) {
1026+
encode_len(w, 6, CBOR_TAG_CLASS);
1027+
encode_string(w, name);
1028+
} else {
1029+
mrb_raise(mrb, E_ARGUMENT_ERROR, "cannot encode anonymous class/module");
1030+
}
1031+
}
1032+
10021033
static void
10031034
encode_simple(CborWriter* w, mrb_value obj)
10041035
{
@@ -1088,6 +1119,8 @@ encode_value(CborWriter* w, mrb_value obj)
10881119
#ifdef MRB_USE_BIGINT
10891120
case MRB_TT_BIGINT: encode_bignum(w, obj); break;
10901121
#endif
1122+
case MRB_TT_CLASS:
1123+
case MRB_TT_MODULE: encode_class(w, obj); break;
10911124
default: {
10921125
mrb_value rev = cbor_tag_rev_registry(mrb);
10931126
mrb_value klass = mrb_obj_value(mrb_class(mrb, obj));
@@ -1822,6 +1855,8 @@ cbor_register_tag_impl(mrb_state *mrb, mrb_value tag_v, mrb_value klass)
18221855
mrb_raisef(mrb, E_ARGUMENT_ERROR,
18231856
"tag %v is reserved for internal CBOR use", tag_v);
18241857
}
1858+
if (unlikely(mrb_integer_p(tag_v) && (uint64_t)mrb_integer(tag_v) == CBOR_TAG_CLASS))
1859+
mrb_raise(mrb, E_ARGUMENT_ERROR, "tag 49999 is reserved for internal CBOR use");
18251860

18261861
{
18271862
struct RClass *kp = mrb_class_ptr(klass);

0 commit comments

Comments
 (0)