DeterministicESPAsyncWebServer v6.27.1
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
msgpack.h
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file msgpack.h
6 * @brief Layer 6 (Presentation) - zero-heap MessagePack encoder and decoder.
7 *
8 * A streaming encoder that writes directly into a caller-provided buffer (no
9 * heap), the MessagePack-format sibling of the CBOR / JSON writers. Each value is
10 * emitted in the shortest MessagePack form (fixint / fixstr / fixarray / fixmap
11 * where possible). Emit definite-length arrays and maps by writing the header
12 * (msgpack_array / msgpack_map with the item count) then that many items (twice
13 * that for a map: key, value, key, value, ...).
14 *
15 * Overflow is tracked, not crashed on: writes past the buffer set the overflow
16 * flag and stop, while msgpack_len() keeps counting the bytes the full payload
17 * would need, so a caller can size the buffer and check msgpack_ok().
18 *
19 * The decoder is a cursor: msgpack_peek() reports the next object's type and the
20 * msgpack_read_* calls consume it (strings and binary point into the source buffer,
21 * no copy). Any malformed or out-of-bounds read sets a sticky error - check
22 * msgpack_reader_ok(). ext and the unused 0xc1 byte are reported as INVALID.
23 *
24 * @author Douglas Quigg (dstroy0)
25 * @date 2026
26 */
27
28#ifndef DETERMINISTICESPASYNCWEBSERVER_MSGPACK_H
29#define DETERMINISTICESPASYNCWEBSERVER_MSGPACK_H
30
31#include "ServerConfig.h"
32#include <stddef.h>
33#include <stdint.h>
34
35#if DETWS_ENABLE_MSGPACK
36
37/** @brief MessagePack encoder state over a caller-provided buffer. */
38struct MsgpackWriter
39{
40 uint8_t *buf; ///< destination buffer.
41 size_t cap; ///< buffer capacity in bytes.
42 size_t pos; ///< bytes the payload needs so far (may exceed cap on overflow).
43 bool overflow; ///< true once a write did not fit.
44};
45
46/** @brief Bind a writer to @p buf (capacity @p cap) and reset it. */
47void msgpack_init(MsgpackWriter *w, uint8_t *buf, size_t cap);
48
49/** @brief Encoded length in bytes (what the full payload needs; compare to cap). */
50size_t msgpack_len(const MsgpackWriter *w);
51
52/** @brief True if every value fit in the buffer. */
53bool msgpack_ok(const MsgpackWriter *w);
54
55void msgpack_uint(MsgpackWriter *w, uint64_t v); ///< unsigned integer
56void msgpack_int(MsgpackWriter *w, int64_t v); ///< signed integer
57void msgpack_bytes(MsgpackWriter *w, const uint8_t *data, size_t len); ///< binary (bin family)
58void msgpack_str(MsgpackWriter *w, const char *s); ///< UTF-8 string (null-terminated)
59void msgpack_str_n(MsgpackWriter *w, const char *s, size_t len); ///< UTF-8 string (explicit length)
60void msgpack_bool(MsgpackWriter *w, bool b); ///< true / false
61void msgpack_nil(MsgpackWriter *w); ///< nil
62void msgpack_float(MsgpackWriter *w, float f); ///< IEEE-754 single (float32, 0xca)
63void msgpack_array(MsgpackWriter *w, size_t count); ///< array header
64void msgpack_map(MsgpackWriter *w, size_t count); ///< map header
65
66// ---------------------------------------------------------------------------
67// Decoder (cursor over a MessagePack byte buffer)
68// ---------------------------------------------------------------------------
69
70/** @brief Type of the next object (returned by msgpack_peek). */
71enum class MsgpackType : uint8_t
72{
73 MSGPACK_TYPE_UINT = 0,
74 MSGPACK_TYPE_INT,
75 MSGPACK_TYPE_BIN,
76 MSGPACK_TYPE_STR,
77 MSGPACK_TYPE_ARRAY,
78 MSGPACK_TYPE_MAP,
79 MSGPACK_TYPE_BOOL,
80 MSGPACK_TYPE_NIL,
81 MSGPACK_TYPE_FLOAT,
82 MSGPACK_TYPE_INVALID ///< end of buffer, a prior error, or an unsupported object (ext / 0xc1)
83};
84
85/** @brief MessagePack decoder cursor over a read-only buffer. */
86struct MsgpackReader
87{
88 const uint8_t *buf; ///< source bytes.
89 size_t len; ///< buffer length.
90 size_t pos; ///< current read offset.
91 bool err; ///< sticky: set on any malformed / out-of-bounds read.
92};
93
94/** @brief Bind a reader to @p buf (length @p len) at offset 0. */
95void msgpack_reader_init(MsgpackReader *r, const uint8_t *buf, size_t len);
96
97/** @brief Type of the next object without consuming it. */
98MsgpackType msgpack_peek(MsgpackReader *r);
99
100/** @brief True while no malformed read has occurred. */
101bool msgpack_reader_ok(const MsgpackReader *r);
102
103bool msgpack_read_uint(MsgpackReader *r, uint64_t *out); ///< unsigned integer (fixint / uint8..64)
104bool msgpack_read_int(MsgpackReader *r, int64_t *out); ///< signed integer (also accepts unsigned)
105bool msgpack_read_bool(MsgpackReader *r, bool *out); ///< true / false
106bool msgpack_read_nil(MsgpackReader *r); ///< nil
107bool msgpack_read_float(MsgpackReader *r, float *out); ///< float32 (0xca) or float64 (0xcb)
108bool msgpack_read_str(MsgpackReader *r, const char **out, size_t *len); ///< str family (points into the buffer)
109bool msgpack_read_bytes(MsgpackReader *r, const uint8_t **out, size_t *len); ///< bin family (points into the buffer)
110bool msgpack_read_array(MsgpackReader *r, size_t *count); ///< array header (object count)
111bool msgpack_read_map(MsgpackReader *r, size_t *count); ///< map header (key/value pair count)
112
113#endif // DETWS_ENABLE_MSGPACK
114#endif // DETERMINISTICESPASYNCWEBSERVER_MSGPACK_H
User-facing configuration for DeterministicESPAsyncWebServer.