feat: wire V4 QBIN host API into RasterArraySource
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled

This commit is contained in:
OpenAI Codex
2026-09-13 14:43:51 +08:00
parent b148fb6a0c
commit ae03d8bfd2
7 changed files with 379 additions and 0 deletions

View File

@@ -11,6 +11,7 @@
#include <atomic>
#include <algorithm>
#include <cctype>
#include <cmath>
namespace mbgl::style {
@@ -22,8 +23,56 @@ namespace {
// same source ID, and that must always invalidate the prior GPU field.
std::atomic_uint64_t nextRasterArrayFieldGeneration{0};
bool validEncodedFieldKey(const std::string& fieldKey) {
if (fieldKey.empty() || fieldKey.size() > 128) return false;
return std::all_of(fieldKey.begin(), fieldKey.end(), [](const unsigned char value) {
return std::isalnum(value) || value == '.' || value == '_' || value == '-' || value == ':';
});
}
bool validRuntimeMetadata(const particle::ingress::EncodedFieldRuntimeMetadata& metadata) {
return !metadata.fieldID.empty() && metadata.fieldID.size() <= 128 && metadata.generation != 0;
}
RasterArrayEncodedFieldSubmitResult mapEncodedFieldStoreResult(const particle::FieldSeriesSubmitResult result) {
switch (result) {
case particle::FieldSeriesSubmitResult::Inserted: return RasterArrayEncodedFieldSubmitResult::AcceptedInserted;
case particle::FieldSeriesSubmitResult::ReplacedRevision:
return RasterArrayEncodedFieldSubmitResult::AcceptedReplacedRevision;
case particle::FieldSeriesSubmitResult::Duplicate: return RasterArrayEncodedFieldSubmitResult::Duplicate;
case particle::FieldSeriesSubmitResult::RejectedInvalidFieldKey:
return RasterArrayEncodedFieldSubmitResult::RejectedInvalidFieldKey;
case particle::FieldSeriesSubmitResult::RejectedIdentityConflict:
return RasterArrayEncodedFieldSubmitResult::RejectedIdentityConflict;
case particle::FieldSeriesSubmitResult::RejectedStaleRevision:
return RasterArrayEncodedFieldSubmitResult::RejectedStaleRevision;
case particle::FieldSeriesSubmitResult::RejectedIncompatibleFrame:
case particle::FieldSeriesSubmitResult::RejectedInvalidFrame:
return RasterArrayEncodedFieldSubmitResult::RejectedIncompatible;
case particle::FieldSeriesSubmitResult::RejectedCapacity:
return RasterArrayEncodedFieldSubmitResult::RejectedCapacity;
}
return RasterArrayEncodedFieldSubmitResult::RejectedIncompatible;
}
} // namespace
const char* rasterArrayEncodedFieldSubmitResultName(const RasterArrayEncodedFieldSubmitResult result) {
switch (result) {
case RasterArrayEncodedFieldSubmitResult::AcceptedInserted: return "AcceptedInserted";
case RasterArrayEncodedFieldSubmitResult::AcceptedReplacedRevision: return "AcceptedReplacedRevision";
case RasterArrayEncodedFieldSubmitResult::Duplicate: return "Duplicate";
case RasterArrayEncodedFieldSubmitResult::RejectedDecode: return "RejectedDecode";
case RasterArrayEncodedFieldSubmitResult::RejectedContract: return "RejectedContract";
case RasterArrayEncodedFieldSubmitResult::RejectedInvalidFieldKey: return "RejectedInvalidFieldKey";
case RasterArrayEncodedFieldSubmitResult::RejectedIdentityConflict: return "RejectedIdentityConflict";
case RasterArrayEncodedFieldSubmitResult::RejectedStaleRevision: return "RejectedStaleRevision";
case RasterArrayEncodedFieldSubmitResult::RejectedIncompatible: return "RejectedIncompatible";
case RasterArrayEncodedFieldSubmitResult::RejectedCapacity: return "RejectedCapacity";
}
return "RejectedIncompatible";
}
RasterArrayTimelineRuntime::RasterArrayTimelineRuntime(std::vector<Entry> entries_)
: entries(std::move(entries_)) {
if (entries.size() < 2) {
@@ -307,6 +356,53 @@ RasterArraySource::~RasterArraySource() {
weakFactory.invalidateWeakPtrs();
}
RasterArrayEncodedFieldSubmitResult RasterArraySource::submitEncodedField(
const std::string& fieldKey,
const particle::ingress::EncodedFieldRuntimeMetadata& runtimeMetadata,
const particle::ResolvedFieldProfileContract& contract,
const std::vector<uint8_t>& rawQbinBytes) {
// Keep every failure before Store::submit side-effect-free. Decoder also
// checks metadata, but validate it here to make the Host ordering explicit.
if (!validEncodedFieldKey(fieldKey)) return RasterArrayEncodedFieldSubmitResult::RejectedInvalidFieldKey;
if (!validRuntimeMetadata(runtimeMetadata)) return RasterArrayEncodedFieldSubmitResult::RejectedDecode;
const auto decoded = particle::ingress::QbinV2Decoder::decode(runtimeMetadata, rawQbinBytes);
if (!decoded.accepted()) return RasterArrayEncodedFieldSubmitResult::RejectedDecode;
if (!particle::FieldProfileValidator::validate(contract, *decoded.frame).accepted())
return RasterArrayEncodedFieldSubmitResult::RejectedContract;
return mapEncodedFieldStoreResult(encodedFieldStore.submit(fieldKey, std::move(decoded.frame)));
}
void RasterArraySource::setColorBinding(particle::ColorBinding binding) { colorBinding = std::move(binding); }
void RasterArraySource::setParticleBinding(particle::ParticleBinding binding) { particleBinding = std::move(binding); }
bool RasterArraySource::setRequestedForecastTime(const uint64_t timestampMs) {
return forecastClock.setRequestedForecastTime(timestampMs);
}
void RasterArraySource::setForecastPlaybackState(const particle::ForecastPlaybackState state) {
state == particle::ForecastPlaybackState::Playing ? forecastClock.play() : forecastClock.pause();
}
bool RasterArraySource::setForecastPlaybackSpeed(const float value) { return forecastClock.setPlaybackSpeed(value); }
bool RasterArraySource::advanceForecastClock(const uint64_t elapsedMs) { return forecastClock.advance(elapsedMs); }
particle::ColorProjectionResult RasterArraySource::resolveColorProjection() const {
if (!colorBinding) return {particle::BindingProjectionError::InvalidBinding, {}};
return particle::BindingProjectionResolver::resolve(encodedFieldStore, *colorBinding, forecastClock.requestedForecastTime());
}
particle::ParticleProjectionResult RasterArraySource::resolveParticleProjection() const {
if (!particleBinding) return {particle::BindingProjectionError::InvalidBinding, {}};
return particle::BindingProjectionResolver::resolve(encodedFieldStore, *particleBinding,
forecastClock.requestedForecastTime());
}
bool RasterArraySource::clearEncodedField(const std::string& fieldKey) { return encodedFieldStore.clear(fieldKey); }
void RasterArraySource::clearAllEncodedFields() { encodedFieldStore.clearAll(); }
const RasterArraySource::Impl& RasterArraySource::impl() const {
return static_cast<const Impl&>(*baseImpl);
}