Skip to content

Commit 5dbcdaa

Browse files
committed
sharedrefs now work with cyclic registered classes and their values too
1 parent 592c1d4 commit 5dbcdaa

2 files changed

Lines changed: 611 additions & 4 deletions

File tree

src/mrb_cbor.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ typedef struct {
4949
const uint8_t *p;
5050
const uint8_t *end;
5151
mrb_int depth;
52+
mrb_int pending_slot;
5253
uint8_t major;
5354
uint8_t info;
5455
} Reader;
@@ -76,6 +77,7 @@ reader_init(Reader* r, const uint8_t* buf, size_t len)
7677
r->p = buf;
7778
r->end = buf + len;
7879
r->depth = 0;
80+
r->pending_slot = -1;
7981
r->major = 0;
8082
r->info = 0;
8183
}
@@ -566,9 +568,11 @@ decode_tag_sharedrefs(mrb_state* mrb, Reader* r,
566568
if (mrb_array_p(sharedrefs)) {
567569
slot = RARRAY_LEN(sharedrefs);
568570
mrb_ary_push(mrb, sharedrefs, mrb_nil_value());
571+
r->pending_slot = slot;
569572
}
570573

571574
mrb_value v = decode_value(mrb, r, src, sharedrefs);
575+
r->pending_slot = -1;
572576

573577
if (slot >= 0) {
574578
mrb_ary_set(mrb, sharedrefs, slot, v);
@@ -2087,9 +2091,14 @@ decode_registered_tag(mrb_state *mrb, Reader *r, mrb_value src,
20872091
if (likely(ttype == MRB_TT_OBJECT)) {
20882092
mrb_value schema = mrb_net_schema(mrb, kp);
20892093
if (likely(mrb_hash_p(schema))) {
2094+
mrb_int slot = r->pending_slot;
2095+
r->pending_slot = -1;
2096+
mrb_value obj = mrb_obj_value(mrb_obj_alloc(mrb, MRB_TT_OBJECT, kp));
2097+
if (slot >= 0 && mrb_array_p(sharedrefs)) {
2098+
mrb_ary_set(mrb, sharedrefs, slot, obj);
2099+
}
20902100
mrb_value payload = decode_value(mrb, r, src, sharedrefs);
20912101
if (likely(mrb_hash_p(payload))) {
2092-
mrb_value obj = mrb_obj_value(mrb_obj_alloc(mrb, MRB_TT_OBJECT, kp));
20932102
decode_ctx ctx = { obj, payload };
20942103
struct RBasic *basic_ptr = mrb_basic_ptr(schema);
20952104
unsigned int was_frozen = basic_ptr->frozen;
@@ -2377,6 +2386,7 @@ cbor_doc_end(mrb_state *mrb, const uint8_t *buf, size_t buf_len, mrb_int offset)
23772386
r.p = buf + offset;
23782387
r.end = buf + buf_len;
23792388
r.depth = 0;
2389+
r.pending_slot = -1;
23802390

23812391
if (unlikely(r.p >= r.end)) return mrb_nil_value();
23822392
if (!skip_cbor_try(mrb, &r)) return mrb_nil_value();
@@ -2409,7 +2419,7 @@ cbor_lazy_value_r(mrb_state *mrb, mrb_value self, mrb_int depth)
24092419

24102420
if (likely((size_t)p->offset < total_len)) {
24112421
Reader r;
2412-
r.base = base; r.p = base + p->offset; r.end = base + total_len; r.depth = depth;
2422+
r.base = base; r.p = base + p->offset; r.end = base + total_len; r.depth = depth; r.pending_slot = -1;
24132423

24142424
mrb_value value = decode_value(mrb, &r, p->buf, sharedrefs);
24152425
if (mrb_data_check_get_ptr(mrb, value, &cbor_lazy_type)) {
@@ -2437,7 +2447,7 @@ lazy_reader_init(mrb_state *mrb, Reader *r, cbor_lazy_t *p)
24372447
const uint8_t *base = (const uint8_t*)RSTRING_PTR(p->buf);
24382448
size_t total_len = (size_t)RSTRING_LEN(p->buf);
24392449
if (likely((size_t)p->offset < total_len)) {
2440-
r->base = base; r->p = base + p->offset; r->end = base + total_len; r->depth = 0;
2450+
r->base = base; r->p = base + p->offset; r->end = base + total_len; r->depth = 0; r->pending_slot = -1;
24412451
} else {
24422452
mrb_raise(mrb, E_RANGE_ERROR, "lazy offset out of bounds");
24432453
}
@@ -2615,7 +2625,7 @@ cbor_lazy_dig(mrb_state *mrb, mrb_value self)
26152625
mrb_raise(mrb, E_RUNTIME_ERROR, "lazy offset out of bounds");
26162626

26172627
Reader r;
2618-
r.base = base; r.p = base + p->offset; r.end = base + total; r.depth = 0;
2628+
r.base = base; r.p = base + p->offset; r.end = base + total; r.depth = 0; r.pending_slot = -1;
26192629
reader_read_header(mrb, &r);
26202630

26212631
mrb_value dig_resolved;

0 commit comments

Comments
 (0)