ProtoCore v0.0.2
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
cloudevents.cpp
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 cloudevents.cpp
6 * @brief CloudEvents v1.0 structured-JSON build + binary-header read.
7 */
8
10
11#if PC_ENABLE_CLOUDEVENTS
12
14#include <string.h>
15
16static bool ce_present(const char *s)
17{
18 return s != nullptr && s[0] != '\0';
19}
20
21// CloudEvents 1.0 JSON attribute names emitted in more than one branch below; named once so the
22// (typo-prone) spec keys stay identical across the has-data / no-data paths. (Flash-resident.)
23static const char *const CE_KEY_DATACONTENTTYPE = "datacontenttype";
24static const char *const CE_KEY_DATA = "data";
25
26size_t pc_cloudevents_build_json(char *buf, size_t cap, const CloudEvent *ce)
27{
28 if (!buf || cap == 0 || !ce)
29 {
30 return 0;
31 }
32 // The three context attributes id/source/type are REQUIRED (CloudEvents 1.0).
33 if (!ce_present(ce->id) || !ce_present(ce->source) || !ce_present(ce->type))
34 {
35 return 0;
36 }
37
38 JsonWriter w(buf, cap);
39 w.begin_object();
40 w.kv_str("specversion", "1.0");
41 w.kv_str("id", ce->id);
42 w.kv_str("source", ce->source);
43 w.kv_str("type", ce->type);
44 if (ce_present(ce->subject))
45 {
46 w.kv_str("subject", ce->subject);
47 }
48
49 // data: a pre-formatted JSON value (verbatim) or a plain string (escaped).
50 if (ce->data_json && ce->data_json[0] != '\0')
51 {
52 w.kv_str(CE_KEY_DATACONTENTTYPE, ce_present(ce->datacontenttype) ? ce->datacontenttype : "application/json");
53 w.key(CE_KEY_DATA);
54 w.raw(ce->data_json);
55 }
56 else if (ce->data_str)
57 {
58 if (ce_present(ce->datacontenttype))
59 {
60 w.kv_str(CE_KEY_DATACONTENTTYPE, ce->datacontenttype);
61 }
62 w.kv_str(CE_KEY_DATA, ce->data_str);
63 }
64 else if (ce_present(ce->datacontenttype))
65 {
66 w.kv_str(CE_KEY_DATACONTENTTYPE, ce->datacontenttype);
67 }
68
69 w.end_object();
70 return w.ok() ? strnlen(buf, cap) : 0;
71}
72
73bool pc_cloudevents_from_headers(const HttpReq *req, CloudEvent *out)
74{
75 if (!req || !out)
76 {
77 return false;
78 }
79 memset(out, 0, sizeof(*out));
80 out->id = http_get_header(req, "ce-id");
81 out->source = http_get_header(req, "ce-source");
82 out->type = http_get_header(req, "ce-type");
83 out->subject = http_get_header(req, "ce-subject");
84 out->datacontenttype = http_get_header(req, "Content-Type");
85 return ce_present(out->id) && ce_present(out->source) && ce_present(out->type);
86}
87
88#endif // PC_ENABLE_CLOUDEVENTS
Builds a JSON document into a fixed caller buffer, no heap.
Definition json.h:59
CloudEvents v1.0 (CNCF) event envelope - structured JSON build + binary (ce-* header) read....
const char * http_get_header(const HttpReq *req, const char *key)
Look up a header value by name (case-insensitive).
Layer 6 (Presentation) - zero-heap JSON: a bounded writer and top-level reader.
Fully-parsed HTTP/1.1 request.