Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions pj_plugins/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,16 @@ target_compile_features(mock_schema_parser_plugin PRIVATE cxx_std_20)
target_compile_options(mock_schema_parser_plugin PRIVATE ${PJ_WARNING_FLAGS})
target_link_libraries(mock_schema_parser_plugin PRIVATE pj_base)

# ---------------------------------------------------------------------------
# Mock Media Parser plugin (declares "object" capability — exercises the
# dual-emit path: scalar `seq` field + opaque blob via objectWriteHost())
# ---------------------------------------------------------------------------

add_library(mock_media_parser_plugin SHARED examples/mock_media_parser.cpp)
target_compile_features(mock_media_parser_plugin PRIVATE cxx_std_20)
target_compile_options(mock_media_parser_plugin PRIVATE ${PJ_WARNING_FLAGS})
target_link_libraries(mock_media_parser_plugin PRIVATE pj_base)

endif() # PJ_BUILD_TESTS

# ---------------------------------------------------------------------------
Expand Down
50 changes: 50 additions & 0 deletions pj_plugins/examples/mock_media_parser.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#include <cstdint>
#include <cstring>
#include <string>
#include <vector>

#include "pj_base/sdk/message_parser_plugin_base.hpp"

namespace {

/// Example parser that exercises the dual-emit path: a scalar `seq` field
/// alongside a raw blob written to the ObjectStore. Payload envelope:
/// bytes [0..8) → little-endian uint64 seq
/// bytes [8..N) → opaque blob (e.g. compressed frame, image, serialized msg)
///
/// The parser declares the `object` capability in its manifest, which signals
/// the host runtime to register the optional `pj.parser_object_write.v1`
/// service so `objectWriteHost()` is non-null inside parse().
class MockMediaParser : public PJ::MessageParserPluginBase {
public:
PJ::Status parse(PJ::Timestamp timestamp_ns, PJ::Span<const uint8_t> payload) override {
if (!writeHostBound()) {
return PJ::unexpected(std::string("write host not bound"));
}
if (payload.size() < sizeof(uint64_t)) {
return PJ::unexpected(std::string("payload too small (need 8 bytes seq prefix)"));
}

uint64_t seq = 0;
std::memcpy(&seq, payload.data(), sizeof(uint64_t));
if (auto s = writeHost().appendRecord(
timestamp_ns, {{.name = "seq", .value = static_cast<uint64_t>(seq)}});
!s) {
return s;
}

if (auto* obj = objectWriteHost()) {
std::vector<uint8_t> body(payload.data() + sizeof(uint64_t), payload.data() + payload.size());
if (auto s = obj->pushOwned(timestamp_ns, std::move(body)); !s) {
return s;
}
}
return PJ::okStatus();
}
};

} // namespace

PJ_MESSAGE_PARSER_PLUGIN(
MockMediaParser,
R"({"id":"mock-media-parser","name":"Mock Media Parser","version":"1.0.0","encoding":["mock-media"],"capabilities":["object"]})")
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ struct RuntimeMessageParserPlugin {
std::string id;
std::string version;
std::vector<std::string> encodings;
std::vector<std::string> capabilities;
std::filesystem::file_time_type loaded_mtime;
};

Expand Down
1 change: 1 addition & 0 deletions pj_plugins/src/plugin_runtime_catalog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ bool PluginRuntimeCatalog::loadAndRegisterMessageParser(const PluginDescriptor&
loaded.name = descriptor.name;
loaded.version = descriptor.version;
loaded.encodings.insert(loaded.encodings.end(), descriptor.encoding.begin(), descriptor.encoding.end());
loaded.capabilities = descriptor.capabilities;

report(DiagnosticLevel::kInfo, loaded.id, "Loaded MessageParser " + loaded.name + " from " + loaded.path);
message_parsers_.push_back(std::move(loaded));
Expand Down
Loading