DAPRequestValidator, DAPCapabilityNegotiator, DAPEventBroadcaster, DAPBreakpointHitDispatcher — 26/26 tests pass. Integration step 1937: Python+Rust DAP session round-trip verified. Also adds allBreakpoints() to ASTNodeBreakpointMapper. Metrics: 8 whetstone calls, 8853 tokens. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
60 lines
1.7 KiB
C++
60 lines
1.7 KiB
C++
#pragma once
|
|
#include <nlohmann/json.hpp>
|
|
#include <functional>
|
|
#include <map>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace whetstone {
|
|
|
|
class DAPEventBroadcaster {
|
|
public:
|
|
using EventHandler = std::function<void(const nlohmann::json&)>;
|
|
|
|
// Subscribe to events of eventType. Returns a subscription id.
|
|
int subscribe(const std::string& eventType, EventHandler handler) {
|
|
int id = nextId_++;
|
|
subs_.push_back({id, eventType, std::move(handler)});
|
|
return id;
|
|
}
|
|
|
|
// Remove the subscription with the given id.
|
|
void unsubscribe(int id) {
|
|
subs_.erase(
|
|
std::remove_if(subs_.begin(), subs_.end(),
|
|
[id](const Sub& s){ return s.id == id; }),
|
|
subs_.end());
|
|
}
|
|
|
|
// Call all handlers registered for eventType, passing body.
|
|
void broadcast(const std::string& eventType, const nlohmann::json& body) const {
|
|
for (const auto& s : subs_)
|
|
if (s.eventType == eventType) s.handler(body);
|
|
}
|
|
|
|
// Broadcast using event["event"] as the type, event itself as the body.
|
|
void broadcastAll(const nlohmann::json& event) const {
|
|
if (!event.contains("event") || !event["event"].is_string()) return;
|
|
broadcast(event["event"].get<std::string>(), event);
|
|
}
|
|
|
|
int subscriberCount(const std::string& eventType) const {
|
|
int n = 0;
|
|
for (const auto& s : subs_)
|
|
if (s.eventType == eventType) ++n;
|
|
return n;
|
|
}
|
|
|
|
private:
|
|
struct Sub {
|
|
int id;
|
|
std::string eventType;
|
|
EventHandler handler;
|
|
};
|
|
|
|
std::vector<Sub> subs_;
|
|
int nextId_ = 1;
|
|
};
|
|
|
|
} // namespace whetstone
|