You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+79-9Lines changed: 79 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -19,9 +19,45 @@
19
19
|**Streaming**|`CBOR.stream` for CBOR sequence reading |
20
20
|**Performance**|~30% faster than msgpack; 1.3–3× faster than simdjson for selective access |
21
21
22
-
### ⚠️ Limitations
22
+
### ⚠️ Limitations & Design Decisions
23
23
24
-
- No indefinite-length item support (RFC 8949 Section 4.2.1)
24
+
| Limitation | Reason |
25
+
|-----------|--------|
26
+
| No indefinite-length items | Use CBOR.stream mode instead. |
27
+
28
+
**Determinism Guarantees:**
29
+
- Encoding is deterministic *within a single mruby build*
30
+
- Hash field order follows insertion order (per mruby hash impl)
31
+
- Float width (16/32/64) is compile-time fixed via `MRB_USE_FLOAT32`
32
+
- Symbol encoding strategy is global; don't mix `no_symbols` / `symbols_as_string` / `symbols_as_uint32` in the same program
33
+
-**Not deterministic across builds** if you rebuild mruby with different CFLAGS or config
34
+
35
+
**Recursion Depth Limits:**
36
+
Default `CBOR_MAX_DEPTH` depends on mruby profile:
37
+
-`MRB_PROFILE_MAIN` / `MRB_PROFILE_HIGH`: 512
38
+
-`MRB_PROFILE_BASELINE`: 64
39
+
- Constrained / other: 32
40
+
41
+
Exceeding this raises `RuntimeError: "CBOR nesting depth exceeded"`. Override by setting `CBOR_MAX_DEPTH` at compile time.
42
+
43
+
---
44
+
45
+
## 📊 Performance Notes
46
+
47
+
-**Encoding:**~30% faster than msgpack (SBO + incremental writes)
48
+
-**Lazy decoding:** 1.3–3× faster than simdjson for selective access
49
+
-**Shared refs:** Tags 28/29 deduplication is O(1) amortized
50
+
-**Float encoding:** No overhead; width selection happens once per value at encode time
51
+
52
+
**When to use lazy decoding:**
53
+
- Decoding large payloads where you only access a subset of fields
54
+
- Streaming/telemetry where you care about specific fields
55
+
- Network protocols where you validate before deserializing
56
+
57
+
**When to use eager decoding:**
58
+
- Small payloads
59
+
- You need the full object in memory instantly
60
+
- Simplicity over optimization
25
61
26
62
---
27
63
@@ -47,7 +83,7 @@ lazy["hello"][1].value # => 2 (constant-time after first access)
47
83
48
84
### CBOR::Lazy – On-Demand Access
49
85
50
-
`decode_lazy` returns a `CBOR::Lazy` object wrapping the raw buffer **without decoding**. Navigate with `[]` or `dig`, then call `.value` when you need the actual value.
86
+
`decode_lazy` returns a `CBOR::Lazy` object wrapping the raw buffer **without decoding the value**. Navigate with `[]` or `dig`, then call `.value` when you need the actual value.
51
87
```ruby
52
88
lazy =CBOR.decode_lazy(big_payload)
53
89
@@ -159,21 +195,41 @@ Convenience Types:
159
195
### Symbol Handling
160
196
161
197
Three strategies for encoding Ruby symbols:
198
+
162
199
```ruby
163
-
# 1. Default: convert to strings (no tag)
200
+
# 1. Default: strip symbols (no tag, no round-trip)
164
201
CBOR.no_symbols
202
+
sym =:hello
203
+
encoded =CBOR.encode(sym) # Encodes as plain string "hello"
204
+
decoded =CBOR.decode(encoded) # => "hello" (not a symbol!)
165
205
166
-
# 2. Use tag 39 + string
206
+
# 2. Use tag 39 + string (RFC 8949, interoperable)
# 3. Use tag 39 + uint32 (mruby presym only, fastest)
170
213
CBOR.symbols_as_uint32
171
214
sym =:hello
172
215
encoded =CBOR.encode(sym)
173
-
decoded =CBOR.decode(encoded) # => :hello
216
+
decoded =CBOR.decode(encoded) # => :hello (symbol preserved, same mruby only)
174
217
```
175
218
176
-
> **⚠️ Warning:**`symbols_as_uint32` is mruby instance–specific. Only use it when both encoder and decoder run on the same mruby executable and when all symbols are interned at compile time, see https://github.com/mruby/mruby/blob/master/doc/guides/symbol.md#preallocate-symbols
|`no_symbols`| Plain string | ✅ All | ❌ No | Fast |
224
+
|`symbols_as_string`| Tag 39 + string | ✅ All | ✅ Yes | Good |
225
+
|`symbols_as_uint32`| Tag 39 + uint32 | ❌ mruby only | ✅ Yes | Fastest |
226
+
227
+
> **⚠️ Warning:**`symbols_as_uint32` requires:
228
+
> -**Same mruby build** — encoder and decoder must use the same mruby executable (same `libmruby.a`)
229
+
> -**Compile-time symbols** — all symbols must be interned at build time (see [presym docs](https://github.com/mruby/mruby/blob/master/doc/guides/symbol.md#preallocate-symbols))
230
+
> -**No runtime symbol creation** — decoding fails if the symbol ID doesn't exist in the decoder's presym table
231
+
>
232
+
> Use only for internal mruby-to-mruby IPC on the same build. For external/user data, use `symbols_as_string`.
0 commit comments