Skip to content

Commit 6d0a98f

Browse files
Copilotpetesramek
andauthored
refactor: make codec layer fully header-only (#23)
* refactor: merge codec cpp files into headers (fully header-only library) Co-authored-by: petesramek <2333452+petesramek@users.noreply.github.com> Agent-Logs-Url: https://github.com/petesramek/tiny-link/sessions/822fb91b-cc43-4f24-8888-79646c3eda00 * fix: restore static inline on packet_size per code review Co-authored-by: petesramek <2333452+petesramek@users.noreply.github.com> Agent-Logs-Url: https://github.com/petesramek/tiny-link/sessions/822fb91b-cc43-4f24-8888-79646c3eda00 --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: petesramek <2333452+petesramek@users.noreply.github.com>
1 parent bbd0a53 commit 6d0a98f

6 files changed

Lines changed: 123 additions & 178 deletions

File tree

src/internal/codec/CobsCodec.cpp

Lines changed: 0 additions & 79 deletions
This file was deleted.

src/internal/codec/CobsCodec.h

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* @file CobsCodec.h
3-
* @brief COBS (Consistent Overhead Byte Stuffing) encode/decode API.
3+
* @brief COBS (Consistent Overhead Byte Stuffing) encode/decode implementation.
44
*
55
* AVR-friendly – no STL dependencies.
66
*/
@@ -23,7 +23,44 @@ namespace codec {
2323
* @param dstCap Capacity of dst in bytes.
2424
* @return Number of bytes written to dst, or 0 on error (dstCap too small).
2525
*/
26-
size_t cobs_encode(const uint8_t* src, size_t srcLen, uint8_t* dst, size_t dstCap);
26+
inline size_t cobs_encode(const uint8_t* src, size_t srcLen, uint8_t* dst, size_t dstCap) {
27+
// Worst-case encoded length: srcLen + (srcLen / 254) + 1
28+
// A safe upper bound is srcLen + 2 (holds for srcLen <= 253).
29+
// For larger inputs the +1 per 254-byte block is handled by the
30+
// overflow check inside the loop.
31+
if (dstCap == 0) return 0;
32+
33+
size_t read_idx = 0, write_idx = 1, code_idx = 0;
34+
uint8_t code = 1;
35+
36+
while (read_idx < srcLen) {
37+
if (src[read_idx] == 0) {
38+
if (code_idx >= dstCap) return 0;
39+
dst[code_idx] = code;
40+
code = 1;
41+
code_idx = write_idx;
42+
if (write_idx >= dstCap) return 0;
43+
write_idx++;
44+
} else {
45+
if (write_idx >= dstCap) return 0;
46+
dst[write_idx++] = src[read_idx];
47+
code++;
48+
if (code == 0xFF) {
49+
if (code_idx >= dstCap) return 0;
50+
dst[code_idx] = code;
51+
code = 1;
52+
code_idx = write_idx;
53+
if (write_idx >= dstCap) return 0;
54+
write_idx++;
55+
}
56+
}
57+
read_idx++;
58+
}
59+
60+
if (code_idx >= dstCap) return 0;
61+
dst[code_idx] = code;
62+
return write_idx;
63+
}
2764

2865
/**
2966
* @brief Decode a COBS-encoded byte buffer.
@@ -34,7 +71,28 @@ size_t cobs_encode(const uint8_t* src, size_t srcLen, uint8_t* dst, size_t dstCa
3471
* @param dstCap Capacity of dst in bytes.
3572
* @return Number of bytes written to dst, or 0 on invalid frame / buffer overflow.
3673
*/
37-
size_t cobs_decode(const uint8_t* src, size_t srcLen, uint8_t* dst, size_t dstCap);
74+
inline size_t cobs_decode(const uint8_t* src, size_t srcLen, uint8_t* dst, size_t dstCap) {
75+
size_t read_idx = 0, write_idx = 0;
76+
77+
while (read_idx < srcLen) {
78+
uint8_t code = src[read_idx++];
79+
80+
if (code == 0 || (read_idx + code - 1) > srcLen)
81+
return 0; // Invalid frame
82+
83+
for (uint8_t i = 1; i < code; i++) {
84+
if (write_idx >= dstCap) return 0;
85+
dst[write_idx++] = src[read_idx++];
86+
}
87+
88+
if (code < 0xFF && read_idx < srcLen) {
89+
if (write_idx >= dstCap) return 0;
90+
dst[write_idx++] = 0;
91+
}
92+
}
93+
94+
return write_idx;
95+
}
3896

3997
} // namespace codec
4098
} // namespace tinylink

src/internal/codec/Fletcher16.cpp

Lines changed: 0 additions & 35 deletions
This file was deleted.

src/internal/codec/Fletcher16.h

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* @file Fletcher16.h
3-
* @brief Fletcher-16 checksum declaration.
3+
* @brief Fletcher-16 checksum implementation.
44
*
55
* AVR-friendly – no STL dependencies.
66
*/
@@ -24,7 +24,23 @@ namespace codec {
2424
* @param len Number of bytes to process.
2525
* @return (sum2 << 8) | sum1
2626
*/
27-
uint16_t fletcher16(const uint8_t* data, size_t len);
27+
inline uint16_t fletcher16(const uint8_t* data, size_t len) {
28+
uint16_t sum1 = 0xff, sum2 = 0xff;
29+
30+
while (len) {
31+
size_t tlen = len > 20 ? 20 : len;
32+
len -= tlen;
33+
do {
34+
sum1 += *data++;
35+
sum2 += sum1;
36+
} while (--tlen);
37+
38+
sum1 = (sum1 & 0xff) + (sum1 >> 8);
39+
sum2 = (sum2 & 0xff) + (sum2 >> 8);
40+
}
41+
42+
return (sum2 << 8) | sum1;
43+
}
2844

2945
} // namespace codec
3046
} // namespace tinylink

src/internal/codec/Packet.cpp

Lines changed: 0 additions & 53 deletions
This file was deleted.

src/internal/codec/Packet.h

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
#include <stddef.h>
55
#include <stdint.h>
6+
#include <string.h>
7+
#include "Fletcher16.h"
68

79
namespace tinylink {
810
namespace packet {
@@ -13,15 +15,51 @@ static inline size_t packet_size(size_t payloadLen) {
1315
}
1416

1517
// Pack a packet into out (outCap >= packet_size(payloadLen)). Returns bytes written or 0 on error.
16-
size_t pack(uint8_t type, uint8_t seq,
17-
const uint8_t* payload, size_t payloadLen,
18-
uint8_t* out, size_t outCap);
18+
inline size_t pack(uint8_t type, uint8_t seq,
19+
const uint8_t* payload, size_t payloadLen,
20+
uint8_t* out, size_t outCap)
21+
{
22+
size_t need = packet_size(payloadLen);
23+
if (!out || outCap < need) return 0;
24+
25+
out[0] = type;
26+
out[1] = seq;
27+
out[2] = (uint8_t)payloadLen;
28+
if (payloadLen && payload) memcpy(&out[3], payload, payloadLen);
29+
30+
// compute checksum over header+payload
31+
uint16_t chk = tinylink::codec::fletcher16(out, 3 + payloadLen);
32+
out[3 + payloadLen + 0] = (uint8_t)(chk & 0xFF);
33+
out[3 + payloadLen + 1] = (uint8_t)((chk >> 8) & 0xFF);
34+
return need;
35+
}
1936

2037
// Unpack a packet. On success returns payload length (>0) and fills outType/outSeq/outPayload (if non-null).
2138
// Returns 0 on error (malformed, length mismatch, checksum failure, or insufficient outPayloadCap).
22-
size_t unpack(const uint8_t* src, size_t srcLen,
23-
uint8_t* outType, uint8_t* outSeq,
24-
uint8_t* outPayload, size_t outPayloadCap);
39+
inline size_t unpack(const uint8_t* src, size_t srcLen,
40+
uint8_t* outType, uint8_t* outSeq,
41+
uint8_t* outPayload, size_t outPayloadCap)
42+
{
43+
if (!src || srcLen < 5) return 0; // min header + checksum
44+
45+
uint8_t payloadLen = src[2];
46+
size_t expected = packet_size(payloadLen);
47+
if (srcLen != expected) return 0;
48+
49+
uint16_t recv = (uint16_t)src[3 + payloadLen + 0] | (uint16_t(src[3 + payloadLen + 1]) << 8);
50+
uint16_t calc = tinylink::codec::fletcher16(src, 3 + payloadLen);
51+
if (calc != recv) return 0;
52+
53+
if (outType) *outType = src[0];
54+
if (outSeq) *outSeq = src[1];
55+
56+
if (outPayload) {
57+
if (outPayloadCap < payloadLen) return 0;
58+
if (payloadLen) memcpy(outPayload, &src[3], payloadLen);
59+
}
60+
61+
return payloadLen;
62+
}
2563

2664
} // namespace packet
2765
} // namespace tinylink

0 commit comments

Comments
 (0)