// assignment_request.cpp — see assignment_request.h. Pure: standard library only. #include "assignment_request.h" #include namespace reasampler { namespace { constexpr const char* kMagic = "rsassign1"; // Append one length-prefixed field: ':' . Mirror of // provenance's putField so the two seams share one wire idiom. void putField(std::string& out, const std::string& field) { out += std::to_string(field.size()); out += ':'; out += field; } // Cursor over the encoded string. All reads are bounds-checked; a short read fails // the whole parse (ok_ latches false). Mirror of provenance's Cursor, trimmed to the // three field kinds this record needs. class Cursor { public: explicit Cursor(const std::string& s) : s_(s) {} bool ok() const { return ok_; } bool atEnd() const { return pos_ >= s_.size(); } // Reads one length-prefixed field into `out`. Fails on a missing ':', an empty or // non-numeric length, or a length that runs past the end. bool field(std::string& out) { if (!ok_) return false; const std::size_t colon = s_.find(':', pos_); if (colon == std::string::npos) return fail(); if (colon == pos_) return fail(); // empty length token std::size_t len = 0; for (std::size_t i = pos_; i < colon; ++i) { const char c = s_[i]; if (c < '0' || c > '9') return fail(); len = len * 10 + static_cast(c - '0'); } const std::size_t start = colon + 1; if (start + len > s_.size()) return fail(); out.assign(s_, start, len); pos_ = start + len; return true; } // Reads a length-prefixed field and parses it as a signed 64-bit decimal (an // optional leading '-'). Fails on empty, non-digit, or trailing bytes. bool fieldInt64(std::int64_t& out) { std::string f; if (!field(f)) return false; if (f.empty()) return fail(); std::size_t i = 0; bool neg = false; if (f[0] == '-') { neg = true; i = 1; if (f.size() == 1) return fail(); // bare "-" } std::int64_t v = 0; for (; i < f.size(); ++i) { const char c = f[i]; if (c < '0' || c > '9') return fail(); v = v * 10 + static_cast(c - '0'); } out = neg ? -v : v; return true; } // Consumes an exact literal at the cursor (the magic tag). Fails if absent. bool literal(const char* lit) { if (!ok_) return false; std::size_t i = 0; for (; lit[i] != '\0'; ++i) { if (pos_ + i >= s_.size() || s_[pos_ + i] != lit[i]) return fail(); } pos_ += i; return true; } private: bool fail() { ok_ = false; return false; } const std::string& s_; std::size_t pos_ = 0; bool ok_ = true; }; } // namespace std::string encodeAssignmentRequest(const AssignmentRequest& req) { std::string out = kMagic; putField(out, req.bankId); putField(out, req.sampleId); putField(out, std::to_string(req.generation)); return out; } std::optional decodeAssignmentRequest(const std::string& wire) { Cursor cur(wire); if (!cur.literal(kMagic)) return std::nullopt; AssignmentRequest req; if (!cur.field(req.bankId)) return std::nullopt; if (!cur.field(req.sampleId)) return std::nullopt; if (!cur.fieldInt64(req.generation)) return std::nullopt; // Reject trailing garbage: a well-formed value ends exactly at the last field. if (!cur.ok() || !cur.atEnd()) return std::nullopt; return req; } } // namespace reasampler