Files
whetstone_DSL/editor/src/TimeTravelDebugEventBuffer.h

87 lines
2.9 KiB
C++

#pragma once
// Step 571: Time-Travel Debug Event Buffer
#include "DebugValidationUtil.h"
#include <cstdint>
#include <deque>
#include <string>
#include <vector>
struct DebugReplayEvent {
std::string eventId;
std::string sessionId;
std::string type;
std::uint64_t instructionPointer = 0;
std::uint64_t timestamp = 0;
std::string payload;
};
class TimeTravelDebugEventBuffer {
public:
explicit TimeTravelDebugEventBuffer(std::size_t capacity = 128)
: capacity_(capacity == 0 ? 1 : capacity) {}
bool append(const DebugReplayEvent& event, std::string* error) {
if (!error) return false;
error->clear();
if (!hasRequiredDebugIds(event.eventId, event.sessionId)) return fail(error, "event_or_session_missing");
if (event.type.empty()) return fail(error, "event_type_missing");
if (!isNonZeroU64(event.timestamp)) return fail(error, "event_timestamp_invalid");
if (!isNonZeroU64(event.instructionPointer)) return fail(error, "event_ip_invalid");
if (containsId(event.eventId)) return fail(error, "event_duplicate");
events_.push_back(event);
while (events_.size() > capacity_) {
events_.pop_front();
++dropped_;
}
return true;
}
std::size_t size() const { return events_.size(); }
std::size_t capacity() const { return capacity_; }
std::size_t droppedCount() const { return dropped_; }
std::vector<DebugReplayEvent> latest(std::size_t count) const {
std::vector<DebugReplayEvent> out;
if (count == 0 || events_.empty()) return out;
const std::size_t begin = events_.size() > count ? events_.size() - count : 0;
for (std::size_t i = begin; i < events_.size(); ++i) out.push_back(events_[i]);
return out;
}
std::vector<DebugReplayEvent> forSession(const std::string& sessionId) const {
std::vector<DebugReplayEvent> out;
for (const auto& event : events_) {
if (sessionId.empty() || event.sessionId == sessionId) out.push_back(event);
}
return out;
}
std::vector<DebugReplayEvent> replayWindow(std::size_t startIndex, std::size_t count) const {
std::vector<DebugReplayEvent> out;
if (count == 0 || startIndex >= events_.size()) return out;
const std::size_t end = (startIndex + count) > events_.size() ? events_.size() : (startIndex + count);
for (std::size_t i = startIndex; i < end; ++i) out.push_back(events_[i]);
return out;
}
private:
std::size_t capacity_ = 128;
std::size_t dropped_ = 0;
std::deque<DebugReplayEvent> events_;
static bool fail(std::string* error, const char* code) {
*error = code;
return false;
}
bool containsId(const std::string& eventId) const {
for (const auto& event : events_) {
if (event.eventId == eventId) return true;
}
return false;
}
};