use std::collections::BTreeMap;
use std::sync::Arc;
use re_sdk_types::blueprint::components::VisualizerInstructionId;
use vec1::Vec1;
use super::{VisualizerInstructionReport, VisualizerReportSeverity};
use crate::{
PerVisualizerTypeInViewClass, ViewContextCollection, ViewSystemExecutionError,
ViewSystemIdentifier, VisualizerCollection, VisualizerExecutionOutput, VisualizerReportContext,
};
pub struct SystemExecutionOutput {
pub view_systems: VisualizerCollection,
pub context_systems: ViewContextCollection,
pub visualizer_execution_output: PerVisualizerTypeInViewClass<
Result<VisualizerExecutionOutput, Arc<ViewSystemExecutionError>>,
>,
}
impl SystemExecutionOutput {
pub fn any_missing_chunks(&self) -> bool {
self.visualizer_execution_output
.per_visualizer
.values()
.filter_map(|result| result.as_ref().ok())
.any(|output| output.any_missing_chunks())
}
pub fn drain_draw_data(&mut self) -> impl Iterator<Item = re_renderer::QueueableDrawData> {
self.visualizer_execution_output
.per_visualizer
.iter_mut()
.filter_map(|(_, result)| {
result
.as_mut()
.ok()
.map(|output| output.draw_data.drain(..))
})
.flatten()
}
}
pub type VisualizerViewReport = BTreeMap<ViewSystemIdentifier, VisualizerTypeReport>;
#[derive(Clone, Debug)]
pub enum VisualizerTypeReport {
OverallError(VisualizerInstructionReport),
PerInstructionReport(BTreeMap<VisualizerInstructionId, Vec1<VisualizerInstructionReport>>),
}
impl re_byte_size::SizeBytes for VisualizerTypeReport {
fn heap_size_bytes(&self) -> u64 {
match self {
Self::OverallError(_err) => 0, Self::PerInstructionReport(reports) => reports.heap_size_bytes(),
}
}
}
impl VisualizerTypeReport {
pub fn from_result(
result: &Result<VisualizerExecutionOutput, Arc<ViewSystemExecutionError>>,
) -> Option<Self> {
match result {
Ok(output) => {
let reports = output.reports_per_instruction.lock();
if reports.is_empty() {
None
} else {
Some(Self::PerInstructionReport(reports.clone()))
}
}
Err(err) => Some(Self::OverallError(VisualizerInstructionReport {
severity: VisualizerReportSeverity::Error,
context: VisualizerReportContext {
component: None,
extra: None,
},
summary: re_error::format_ref(err),
details: None,
})),
}
}
pub fn reports_for(
&self,
instruction_id: &VisualizerInstructionId,
) -> impl Iterator<Item = &VisualizerInstructionReport> {
match self {
Self::OverallError(report) => itertools::Either::Left(std::iter::once(report)),
Self::PerInstructionReport(reports) => itertools::Either::Right(
reports
.get(instruction_id)
.map_or([].as_slice(), |r| r.as_slice())
.iter(),
),
}
}
pub fn reports_for_component(
&self,
instruction_id: &VisualizerInstructionId,
component: re_chunk::ComponentIdentifier,
) -> impl Iterator<Item = &VisualizerInstructionReport> {
self.reports_for(instruction_id)
.filter(move |report| report.context.component == Some(component))
}
pub fn reports_without_component(
&self,
instruction_id: &VisualizerInstructionId,
) -> impl Iterator<Item = &VisualizerInstructionReport> {
self.reports_for(instruction_id)
.filter(|report| report.context.component.is_none())
}
pub fn highest_severity_for(
&self,
instruction_id: &VisualizerInstructionId,
) -> Option<VisualizerReportSeverity> {
match self {
Self::OverallError(_) => Some(VisualizerReportSeverity::Error),
Self::PerInstructionReport(reports) => reports
.get(instruction_id)?
.iter()
.map(|r| r.severity)
.max(),
}
}
}