gsm_core/
render_mode.rs

1//! Render mode abstraction to toggle between legacy rendering and the planner path.
2use crate::{
3    provider_capabilities::ProviderCapabilitiesV1,
4    provider_registry::ProviderCapsRegistry,
5    render_plan::{RenderPlan, RenderTier, RenderWarning},
6    render_planner::{PlannerCard, plan_render, planner_policy},
7};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
10pub enum RenderMode {
11    #[default]
12    Legacy,
13    Planned,
14}
15
16/// Result of a render decision.
17#[derive(Debug, Clone, PartialEq)]
18pub struct RenderOutcome {
19    pub mode: RenderMode,
20    pub plan: Option<RenderPlan>,
21    pub warnings: Vec<RenderWarning>,
22}
23
24impl RenderOutcome {
25    pub fn tier(&self) -> RenderTier {
26        self.plan
27            .as_ref()
28            .map(|p| p.tier)
29            .unwrap_or(RenderTier::TierD)
30    }
31}
32
33/// Decide how to render based on render mode and provider capabilities.
34///
35/// Legacy mode bypasses the planner and returns no plan.
36/// Planned mode pulls capabilities from the registry (or a supplied fallback) and runs the planner.
37pub fn compute_render_outcome(
38    mode: RenderMode,
39    provider_id: &str,
40    card: &PlannerCard,
41    registry: &ProviderCapsRegistry,
42    caps_fallback: Option<&ProviderCapabilitiesV1>,
43) -> RenderOutcome {
44    match mode {
45        RenderMode::Legacy => RenderOutcome {
46            mode,
47            plan: None,
48            warnings: Vec::new(),
49        },
50        RenderMode::Planned => {
51            let caps = registry
52                .get_caps(provider_id)
53                .or(caps_fallback)
54                .cloned()
55                .unwrap_or_default();
56            let plan = plan_render(card, &caps, &planner_policy());
57            let warnings = plan.warnings.clone();
58            RenderOutcome {
59                mode,
60                plan: Some(plan),
61                warnings,
62            }
63        }
64    }
65}