Skip to content

Commit f18c877

Browse files
committed
feat: add sentry__value_from_msgpack (#1492)
1 parent 06eee53 commit f18c877

4 files changed

Lines changed: 433 additions & 0 deletions

File tree

src/sentry_value.c

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1622,3 +1622,108 @@ sentry_event_value_add_stacktrace(sentry_value_t event, void **ips, size_t len)
16221622
sentry_value_set_stacktrace(thread, ips, len);
16231623
sentry_event_add_thread(event, thread);
16241624
}
1625+
1626+
static sentry_value_t
1627+
value_from_mpack(mpack_node_t node)
1628+
{
1629+
switch (mpack_node_type(node)) {
1630+
case mpack_type_nil:
1631+
return sentry_value_new_null();
1632+
case mpack_type_bool:
1633+
return sentry_value_new_bool(mpack_node_bool(node));
1634+
case mpack_type_int: {
1635+
int64_t i64_val = mpack_node_i64(node);
1636+
if (i64_val >= INT32_MIN && i64_val <= INT32_MAX) {
1637+
return sentry_value_new_int32((int32_t)i64_val);
1638+
} else {
1639+
return sentry_value_new_int64(i64_val);
1640+
}
1641+
}
1642+
case mpack_type_uint: {
1643+
uint64_t u64_val = mpack_node_u64(node);
1644+
if (u64_val <= INT32_MAX) {
1645+
return sentry_value_new_int32((int32_t)u64_val);
1646+
} else if (u64_val <= INT64_MAX) {
1647+
return sentry_value_new_int64((int64_t)u64_val);
1648+
} else {
1649+
return sentry_value_new_uint64(u64_val);
1650+
}
1651+
}
1652+
case mpack_type_float:
1653+
case mpack_type_double:
1654+
return sentry_value_new_double(mpack_node_double(node));
1655+
case mpack_type_str: {
1656+
size_t str_len = mpack_node_strlen(node);
1657+
return sentry_value_new_string_n(mpack_node_str(node), str_len);
1658+
}
1659+
case mpack_type_array: {
1660+
size_t arr_len = mpack_node_array_length(node);
1661+
sentry_value_t arr = sentry_value_new_list();
1662+
for (size_t i = 0; i < arr_len; i++) {
1663+
sentry_value_append(
1664+
arr, value_from_mpack(mpack_node_array_at(node, i)));
1665+
}
1666+
return arr;
1667+
}
1668+
case mpack_type_map: {
1669+
size_t map_len = mpack_node_map_count(node);
1670+
sentry_value_t obj = sentry_value_new_object();
1671+
for (size_t i = 0; i < map_len; i++) {
1672+
mpack_node_t key_node = mpack_node_map_key_at(node, i);
1673+
if (mpack_node_type(key_node) != mpack_type_str) {
1674+
continue; // skip non-string keys
1675+
}
1676+
mpack_node_t val_node = mpack_node_map_value_at(node, i);
1677+
size_t key_len = mpack_node_strlen(key_node);
1678+
sentry_value_set_by_key_n(obj, mpack_node_str(key_node), key_len,
1679+
value_from_mpack(val_node));
1680+
}
1681+
return obj;
1682+
}
1683+
case mpack_type_missing:
1684+
case mpack_type_bin:
1685+
default:
1686+
return sentry_value_new_null();
1687+
}
1688+
}
1689+
1690+
sentry_value_t
1691+
sentry__value_from_msgpack(const char *buf, size_t buf_len)
1692+
{
1693+
if (!buf || buf_len == 0) {
1694+
return sentry_value_new_null();
1695+
}
1696+
1697+
size_t offset = 0;
1698+
sentry_value_t result = sentry_value_new_null();
1699+
1700+
while (offset < buf_len) {
1701+
mpack_tree_t tree;
1702+
mpack_tree_init_data(&tree, buf + offset, buf_len - offset);
1703+
mpack_tree_parse(&tree);
1704+
1705+
if (mpack_tree_error(&tree) != mpack_ok) {
1706+
mpack_tree_destroy(&tree);
1707+
break;
1708+
}
1709+
1710+
size_t size = mpack_tree_size(&tree);
1711+
sentry_value_t value = value_from_mpack(mpack_tree_root(&tree));
1712+
mpack_tree_destroy(&tree);
1713+
1714+
if (offset == 0 && sentry_value_is_null(result)) {
1715+
if (offset + size < buf_len) {
1716+
result = sentry_value_new_list();
1717+
sentry_value_append(result, value);
1718+
} else {
1719+
result = value;
1720+
}
1721+
} else {
1722+
sentry_value_append(result, value);
1723+
}
1724+
1725+
offset += size;
1726+
}
1727+
1728+
return result;
1729+
}

src/sentry_value.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,4 +107,14 @@ int sentry__value_merge_objects(sentry_value_t dst, sentry_value_t src);
107107
void sentry__jsonwriter_write_value(
108108
sentry_jsonwriter_t *jw, sentry_value_t value);
109109

110+
/**
111+
* Deserialize a sentry value from msgpack.
112+
*
113+
* If the buffer contains multiple sequential msgpack values (as in flat buffers
114+
* like breadcrumb files), they are automatically wrapped in a list.
115+
*
116+
* The returned value must be released with `sentry_value_decref`.
117+
*/
118+
sentry_value_t sentry__value_from_msgpack(const char *buf, size_t buf_len);
119+
110120
#endif

0 commit comments

Comments
 (0)