-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.c
More file actions
101 lines (88 loc) · 2.99 KB
/
Copy pathmain.c
File metadata and controls
101 lines (88 loc) · 2.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gremlin.h"
#include "example.pb.h"
static void
print_bytes(const char *label, struct gremlin_bytes b)
{
printf(" %s: \"%.*s\" (%zu bytes)\n",
label, (int)b.len, (const char *)b.data, b.len);
}
static const char *
role_name(int32_t r)
{
switch (r) {
case example_Role_GUEST: return "GUEST";
case example_Role_USER: return "USER";
case example_Role_ADMIN: return "ADMIN";
default: return "?";
}
}
int
main(void)
{
/* Writer structs are plain-old-data; sub-messages are passed by
* pointer and the writer takes no ownership. */
example_Address addr = {
.city = { .data = (const uint8_t *)"Berlin", .len = 6 },
.country = { .data = (const uint8_t *)"Germany", .len = 7 },
.zip = 10115,
};
struct gremlin_bytes tags[] = {
{ .data = (const uint8_t *)"admin", .len = 5 },
{ .data = (const uint8_t *)"member", .len = 6 },
};
example_Person p = {
.name = { .data = (const uint8_t *)"Ada Lovelace", .len = 12 },
.age = 36,
.role = example_Role_ADMIN,
.address = &addr,
.tags = tags,
.tags_count = sizeof tags / sizeof tags[0],
};
/* Two-step encode: `_size` returns the exact byte count and caches
* it on the struct (used for nested-message length prefixes);
* `_encode` writes into a caller-provided writer. No heap use
* inside the runtime — we own the buffer. */
size_t need = example_Person_size(&p);
uint8_t *buf = malloc(need);
if (buf == NULL) return 1;
struct gremlin_writer w;
gremlin_writer_init(&w, buf, need);
example_Person_encode(&p, &w);
printf("encoded %zu bytes\n", w.offset);
/* Readers are zero-copy views over the caller's buffer: `_reader_init`
* walks the wire format once to cache field offsets; `_reader_get_*`
* then returns values (or sub-readers) without touching the heap. */
example_Person_reader r;
enum gremlin_error err = example_Person_reader_init(&r, buf, w.offset);
if (err != GREMLIN_OK) {
fprintf(stderr, "decode failed: error %d\n", err);
free(buf);
return 1;
}
printf("\nPerson:\n");
print_bytes("name", example_Person_reader_get_name(&r));
printf(" age: %d\n", example_Person_reader_get_age(&r));
printf(" role: %s\n", role_name(example_Person_reader_get_role(&r)));
example_Address_reader addr_r;
err = example_Person_reader_get_address(&r, &addr_r);
if (err == GREMLIN_OK) {
printf(" address:\n");
print_bytes(" city", example_Address_reader_get_city(&addr_r));
print_bytes(" country", example_Address_reader_get_country(&addr_r));
printf(" zip: %d\n", example_Address_reader_get_zip(&addr_r));
}
size_t tag_count = example_Person_reader_tags_count(&r);
printf(" tags (%zu):\n", tag_count);
example_Person_reader_tags_iter it = example_Person_reader_tags_begin(&r);
for (size_t i = 0; i < tag_count; i++) {
struct gremlin_bytes tag;
err = example_Person_reader_tags_next(&it, &tag);
if (err != GREMLIN_OK) break;
print_bytes(" ", tag);
}
free(buf);
return 0;
}