Host C Specs


Directory: src/c/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 100.0% 32 / 0 / 32
Functions: 100.0% 1 / 0 / 1
Branches: 88.9% 16 / 0 / 18

core/wire/calendar_wire.c
Line Branch Exec Source
1 /**
2 * @file calendar_wire.c
3 * @brief The agenda as the phone packs it, and the reader that unpacks it.
4 *
5 * @ingroup lib_core
6 */
7 #include "wire/calendar_wire.h"
8
9 #include "io/bytes_le.h"
10 #include "text/number_format.h"
11
12 11 bool calendar_wire_decode(const uint8_t *buf, uint16_t len, CalendarStrip *out)
13 {
14
4/6
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 10 times.
11 if (!buf || !out || len < 1)
15 {
16 1 return false;
17 }
18
19 10 uint8_t count = buf[0];
20
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 9 times.
10 if (count > CALENDAR_SLOTS_MAX)
21 {
22 // the phone's word for how many, pinned to how many there is room for. without this the
23 // fill below walks straight off the end of the event array
24 1 count = CALENDAR_SLOTS_MAX;
25 }
26
27 // zero-init so the unused slot[count..MAX-1] bytes are deterministic, not stale
28 // stack, once the whole strip gets persisted to flash
29 10 CalendarStrip built = {0};
30
31 10 uint16_t offset = 1;
32
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 5 times.
20 for (uint8_t i = 0; i < count; i++)
33 {
34 // the fixed part of an event is start(4) + end(4) + flags(1) + titleLen(1) = 10 bytes
35
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 13 times.
15 if (offset + 10 > len)
36 {
37 2 return false; // malformed, the caller keeps the old strip
38 }
39
40 13 CalendarEvent *event = &built.event[i];
41 13 event->start = (time_t)read_i32_le(buf + offset);
42 13 event->end = (time_t)read_i32_le(buf + offset + 4);
43 13 event->all_day = (buf[offset + 8] & 0x01) != 0;
44 13 uint8_t title_len = buf[offset + 9];
45 13 offset += 10;
46
47
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 12 times.
13 if (offset + title_len > len)
48 {
49 1 return false; // title runs past the buffer
50 }
51 12 copy_bounded(event->title, CAL_TITLE_LEN, buf + offset, title_len);
52 12 offset += title_len;
53
54 // location is length-prefixed the same way, right after the title
55
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 11 times.
12 if (offset + 1 > len)
56 {
57 1 return false;
58 }
59 11 uint8_t loc_len = buf[offset];
60 11 offset += 1;
61
62
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 10 times.
11 if (offset + loc_len > len)
63 {
64 1 return false; // location runs past the buffer
65 }
66 10 copy_bounded(event->location, CAL_LOC_LEN, buf + offset, loc_len);
67 10 offset += loc_len;
68
69 10 built.count++;
70 }
71
72 // only now, once the whole run has read clean
73 5 *out = built;
74 5 return true;
75 }
76