Line | Count | Source (jump to first uncovered line) |
1 | | /* SPDX-License-Identifier: GPL-3.0-or-later |
2 | | * Copyright © 2022-2025 The TokTok team. |
3 | | */ |
4 | | |
5 | | #include "bin_pack.h" |
6 | | |
7 | | #include <assert.h> |
8 | | #include <string.h> |
9 | | |
10 | | #include "../third_party/cmp/cmp.h" |
11 | | #include "attributes.h" |
12 | | #include "ccompat.h" |
13 | | #include "logger.h" |
14 | | |
15 | | struct Bin_Pack { |
16 | | uint8_t *bytes; |
17 | | uint32_t bytes_size; |
18 | | uint32_t bytes_pos; |
19 | | cmp_ctx_t ctx; |
20 | | }; |
21 | | |
22 | | static bool null_reader(cmp_ctx_t *_Nonnull ctx, void *_Nonnull data, size_t limit) |
23 | 0 | { |
24 | 0 | assert(limit == 0); |
25 | 0 | return false; |
26 | 0 | } |
27 | | |
28 | | static bool null_skipper(cmp_ctx_t *_Nonnull ctx, size_t count) |
29 | 0 | { |
30 | 0 | assert(count == 0); |
31 | 0 | return false; |
32 | 0 | } |
33 | | |
34 | | static size_t buf_writer(cmp_ctx_t *_Nonnull ctx, const void *_Nonnull data, size_t count) |
35 | 7.05M | { |
36 | 7.05M | const uint8_t *bytes = (const uint8_t *)data; |
37 | 7.05M | Bin_Pack *bp = (Bin_Pack *)ctx->buf; |
38 | 7.05M | assert(bp != nullptr); |
39 | 7.05M | const uint32_t new_pos = bp->bytes_pos + count; |
40 | 7.05M | if (new_pos < bp->bytes_pos) { |
41 | | // 32 bit overflow. |
42 | 0 | return 0; |
43 | 0 | } |
44 | 7.05M | if (bp->bytes != nullptr) { |
45 | 3.51M | if (new_pos > bp->bytes_size) { |
46 | | // Buffer too small. |
47 | 1 | return 0; |
48 | 1 | } |
49 | 3.51M | memcpy(&bp->bytes[bp->bytes_pos], bytes, count); |
50 | 3.51M | } |
51 | 7.05M | bp->bytes_pos += count; |
52 | 7.05M | return count; |
53 | 7.05M | } |
54 | | |
55 | | static void bin_pack_init(Bin_Pack *_Nonnull bp, uint8_t *_Nullable buf, uint32_t buf_size) |
56 | 1.10M | { |
57 | 1.10M | bp->bytes = buf; |
58 | 1.10M | bp->bytes_size = buf_size; |
59 | 1.10M | bp->bytes_pos = 0; |
60 | 1.10M | cmp_init(&bp->ctx, bp, null_reader, null_skipper, buf_writer); |
61 | 1.10M | } |
62 | | |
63 | | uint32_t bin_pack_obj_size(bin_pack_cb *callback, const void *obj, const Logger *logger) |
64 | 142k | { |
65 | 142k | Bin_Pack bp; |
66 | 142k | bin_pack_init(&bp, nullptr, 0); |
67 | 142k | if (!callback(obj, logger, &bp)) { |
68 | 0 | return UINT32_MAX; |
69 | 0 | } |
70 | 142k | return bp.bytes_pos; |
71 | 142k | } |
72 | | |
73 | | bool bin_pack_obj(bin_pack_cb *callback, const void *obj, const Logger *logger, uint8_t *buf, uint32_t buf_size) |
74 | 140k | { |
75 | 140k | Bin_Pack bp; |
76 | 140k | bin_pack_init(&bp, buf, buf_size); |
77 | 140k | return callback(obj, logger, &bp); |
78 | 140k | } |
79 | | |
80 | | uint32_t bin_pack_obj_array_b_size(bin_pack_array_cb *callback, const void *arr, uint32_t arr_size, const Logger *logger) |
81 | 410k | { |
82 | 410k | Bin_Pack bp; |
83 | 410k | bin_pack_init(&bp, nullptr, 0); |
84 | 410k | if (arr == nullptr) { |
85 | 0 | assert(arr_size == 0); |
86 | 0 | } |
87 | 1.00M | for (uint32_t i = 0; i < arr_size; ++i) { |
88 | 592k | if (!callback(arr, i, logger, &bp)) { |
89 | 2.81k | return UINT32_MAX; |
90 | 2.81k | } |
91 | 592k | } |
92 | 407k | return bp.bytes_pos; |
93 | 410k | } |
94 | | |
95 | | bool bin_pack_obj_array_b(bin_pack_array_cb *callback, const void *arr, uint32_t arr_size, const Logger *logger, uint8_t *buf, uint32_t buf_size) |
96 | 410k | { |
97 | 410k | Bin_Pack bp; |
98 | 410k | bin_pack_init(&bp, buf, buf_size); |
99 | 410k | if (arr == nullptr) { |
100 | 0 | assert(arr_size == 0); |
101 | 0 | } |
102 | 1.00M | for (uint32_t i = 0; i < arr_size; ++i) { |
103 | 592k | if (!callback(arr, i, logger, &bp)) { |
104 | 2.81k | return false; |
105 | 2.81k | } |
106 | 592k | } |
107 | 407k | return true; |
108 | 410k | } |
109 | | |
110 | | bool bin_pack_obj_array(Bin_Pack *bp, bin_pack_array_cb *callback, const void *arr, uint32_t arr_size, const Logger *logger) |
111 | 3.20k | { |
112 | 3.20k | if (arr == nullptr) { |
113 | 2.69k | assert(arr_size == 0); |
114 | 2.69k | return bin_pack_array(bp, 0); |
115 | 2.69k | } |
116 | | |
117 | 510 | if (!bin_pack_array(bp, arr_size)) { |
118 | 0 | return false; |
119 | 0 | } |
120 | | |
121 | 2.40k | for (uint32_t i = 0; i < arr_size; ++i) { |
122 | 1.89k | if (!callback(arr, i, logger, bp)) { |
123 | 0 | return false; |
124 | 0 | } |
125 | 1.89k | } |
126 | | |
127 | 510 | return true; |
128 | 510 | } |
129 | | |
130 | | bool bin_pack_array(Bin_Pack *bp, uint32_t size) |
131 | 12.5k | { |
132 | 12.5k | return cmp_write_array(&bp->ctx, size); |
133 | 12.5k | } |
134 | | |
135 | | bool bin_pack_bool(Bin_Pack *bp, bool val) |
136 | 489 | { |
137 | 489 | return cmp_write_bool(&bp->ctx, val); |
138 | 489 | } |
139 | | |
140 | | bool bin_pack_u08(Bin_Pack *bp, uint8_t val) |
141 | 1.78k | { |
142 | 1.78k | return cmp_write_uinteger(&bp->ctx, val); |
143 | 1.78k | } |
144 | | |
145 | | bool bin_pack_u16(Bin_Pack *bp, uint16_t val) |
146 | 3.91k | { |
147 | 3.91k | return cmp_write_uinteger(&bp->ctx, val); |
148 | 3.91k | } |
149 | | |
150 | | bool bin_pack_u32(Bin_Pack *bp, uint32_t val) |
151 | 6.05k | { |
152 | 6.05k | return cmp_write_uinteger(&bp->ctx, val); |
153 | 6.05k | } |
154 | | |
155 | | bool bin_pack_u64(Bin_Pack *bp, uint64_t val) |
156 | 172 | { |
157 | 172 | return cmp_write_uinteger(&bp->ctx, val); |
158 | 172 | } |
159 | | |
160 | | bool bin_pack_bin(Bin_Pack *bp, const uint8_t *data, uint32_t length) |
161 | 7.63k | { |
162 | 7.63k | return cmp_write_bin(&bp->ctx, data, length); |
163 | 7.63k | } |
164 | | |
165 | | bool bin_pack_nil(Bin_Pack *bp) |
166 | 229 | { |
167 | 229 | return cmp_write_nil(&bp->ctx); |
168 | 229 | } |
169 | | |
170 | | bool bin_pack_bin_marker(Bin_Pack *bp, uint32_t size) |
171 | 2 | { |
172 | 2 | return cmp_write_bin_marker(&bp->ctx, size); |
173 | 2 | } |
174 | | |
175 | | bool bin_pack_u08_b(Bin_Pack *bp, uint8_t val) |
176 | 4.36M | { |
177 | 4.36M | return bp->ctx.write(&bp->ctx, &val, 1) == 1; |
178 | 4.36M | } |
179 | | |
180 | | bool bin_pack_u16_b(Bin_Pack *bp, uint16_t val) |
181 | 1.45M | { |
182 | 1.45M | return bin_pack_u08_b(bp, (val >> 8) & 0xff) |
183 | 1.45M | && bin_pack_u08_b(bp, val & 0xff); |
184 | 1.45M | } |
185 | | |
186 | | bool bin_pack_u32_b(Bin_Pack *bp, uint32_t val) |
187 | 6 | { |
188 | 6 | return bin_pack_u16_b(bp, (val >> 16) & 0xffff) |
189 | 6 | && bin_pack_u16_b(bp, val & 0xffff); |
190 | 6 | } |
191 | | |
192 | | bool bin_pack_u64_b(Bin_Pack *bp, uint64_t val) |
193 | 3 | { |
194 | 3 | return bin_pack_u32_b(bp, (val >> 32) & 0xffffffff) |
195 | 3 | && bin_pack_u32_b(bp, val & 0xffffffff); |
196 | 3 | } |
197 | | |
198 | | bool bin_pack_bin_b(Bin_Pack *bp, const uint8_t *data, uint32_t length) |
199 | 2.63M | { |
200 | 2.63M | return bp->ctx.write(&bp->ctx, data, length) == length; |
201 | 2.63M | } |