use crate::sdf;
use super::QueryError;
use super::asset_resolve::AssetSite;
use super::clip::{ClipCache, ClipQuery, ResolvedClipSet};
use super::diagnostics::Diagnostics;
use super::layer_graph::StackIdentity;
use super::prim_graph::{ArcType, Node};
use super::{LayerGraph, LayerId, LayerStackId, LayerStackIdentifier, MapFunction};
#[derive(Debug, Clone, Copy, PartialEq)]
pub(crate) enum ResolveMode {
Proximal,
Default,
Numeric(f64),
}
impl ResolveMode {
pub(crate) fn visits_time_samples(self) -> bool {
!matches!(self, Self::Default)
}
pub(crate) fn consults_clips(self) -> bool {
!matches!(self, Self::Default)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[must_use]
pub(crate) enum Step {
Continue,
Stop,
}
impl Step {
pub(crate) fn stop(self) -> bool {
matches!(self, Self::Stop)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum Withheld {
DefaultBlock,
TimeSamplesFieldBlock,
}
pub(crate) enum SampleField<'a> {
Map(&'a sdf::TimeSampleMap),
Blocked,
Unusable,
}
impl<'a> SampleField<'a> {
pub(crate) fn classify(value: &'a sdf::Value) -> Self {
match value {
sdf::Value::TimeSamples(samples) if !samples.is_empty() => Self::Map(samples),
sdf::Value::ValueBlock | sdf::Value::None => Self::Blocked,
_ => Self::Unusable,
}
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub(crate) enum ValueState {
Present,
Blocked,
#[default]
Absent,
}
#[derive(Debug, Default)]
pub(crate) struct Resolution {
pub(crate) source: ResolveSourceKind,
pub(crate) node: Option<ResolveNode>,
pub(crate) value: ValueState,
pub(crate) authored: bool,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub(crate) enum ResolveSourceKind {
#[default]
None,
Default,
TimeSamples,
ValueClips,
}
pub(crate) fn samples_supply_value(
samples: &sdf::TimeSampleMap,
offset: sdf::LayerOffset,
time: Option<f64>,
interp: &dyn Fn(&sdf::TimeSampleMap, f64) -> Option<sdf::Value>,
) -> bool {
match time {
Some(time) => offset.sample_in_stage_time(samples, time, interp).is_some(),
None => samples_supply_any_value(samples),
}
}
pub(crate) fn samples_supply_any_value(samples: &sdf::TimeSampleMap) -> bool {
samples.iter().any(|(_, value)| !is_block(value))
}
pub(crate) fn is_block(value: &sdf::Value) -> bool {
matches!(value, sdf::Value::ValueBlock | sdf::Value::None)
}
#[derive(Debug, Clone, PartialEq)]
pub struct ResolveNode {
arc: ArcType,
path: sdf::Path,
map_to_root: MapFunction,
layer_stack: ResolveStackIdentity,
}
impl ResolveNode {
pub(crate) fn capture(graph: &LayerGraph, node: &Node, stage: &LayerStackIdentifier) -> Self {
Self {
arc: node.arc,
path: node.path.clone(),
map_to_root: node.map_to_root.clone(),
layer_stack: ResolveStackIdentity {
stage: stage.clone(),
stack: Box::new(graph.stack_identity(node.layer_stack)),
},
}
}
pub fn arc(&self) -> ArcType {
self.arc
}
pub fn path(&self) -> &sdf::Path {
&self.path
}
pub fn map_to_root(&self) -> &MapFunction {
&self.map_to_root
}
pub fn layer_stack(&self) -> &ResolveStackIdentity {
&self.layer_stack
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct ResolveStackIdentity {
stage: LayerStackIdentifier,
stack: Box<StackIdentity>,
}
impl ResolveStackIdentity {
pub fn stage(&self) -> &LayerStackIdentifier {
&self.stage
}
pub fn stack(&self) -> &StackIdentity {
&self.stack
}
}
pub(crate) struct OpinionSite<'a> {
pub(crate) node: &'a Node,
pub(crate) layer: LayerId,
pub(crate) offset: sdf::LayerOffset,
pub(crate) query_path: sdf::Path,
}
#[derive(Debug, Clone)]
pub(crate) struct SelectedSite {
pub(crate) layer: LayerId,
pub(crate) layer_stack: LayerStackId,
pub(crate) query_path: sdf::Path,
}
impl SelectedSite {
pub(crate) fn is(&self, layer: LayerId, node: &Node, path: &sdf::Path) -> bool {
self.layer == layer && self.layer_stack == node.layer_stack_id() && self.query_path == *path
}
}
impl OpinionSite<'_> {
pub(crate) fn select(&self) -> SelectedSite {
SelectedSite {
layer: self.layer,
layer_stack: self.node.layer_stack_id(),
query_path: self.query_path.clone(),
}
}
pub(crate) fn asset_site(&self, graph: &LayerGraph) -> AssetSite {
AssetSite::in_graph(graph, self.node.layer_stack_id(), self.layer, &self.query_path)
}
}
pub(crate) struct ClipProbe<'a> {
pub(crate) cache: &'a mut ClipCache,
pub(crate) graph: &'a LayerGraph,
pub(crate) diagnostics: &'a mut Diagnostics,
pub(crate) set: &'a ResolvedClipSet,
pub(crate) query: ClipQuery<'a>,
}
pub(crate) enum ClipAnswer {
Absent,
Blocked,
Value(sdf::Value),
}
impl ClipAnswer {
pub(crate) fn value_state(&self) -> ValueState {
match self {
Self::Absent => ValueState::Absent,
Self::Blocked => ValueState::Blocked,
Self::Value(_) => ValueState::Present,
}
}
pub(crate) fn into_value(self) -> Option<sdf::Value> {
match self {
Self::Value(value) => Some(value),
Self::Absent | Self::Blocked => None,
}
}
}
impl ClipProbe<'_> {
pub(crate) fn answer_at(
&mut self,
time: f64,
interp: &dyn Fn(&sdf::TimeSampleMap, f64) -> Option<sdf::Value>,
) -> Result<ClipAnswer, QueryError> {
match self
.cache
.value_in_set(self.graph, self.diagnostics, self.set, &self.query, time, interp)?
{
None => Ok(ClipAnswer::Absent),
Some(value) if is_block(&value) => Ok(ClipAnswer::Blocked),
Some(value) => Ok(ClipAnswer::Value(value)),
}
}
pub(crate) fn answer_untimed(&mut self) -> Result<ValueState, QueryError> {
self.cache
.untimed_answer_in_set(self.graph, self.diagnostics, self.set, &self.query)
}
pub(crate) fn introspection(&mut self) -> Result<Option<(Vec<f64>, bool)>, QueryError> {
self.cache
.clip_introspection_in_set(self.graph, self.diagnostics, self.set, &self.query)
}
pub(crate) fn spec_site_at(&mut self, time: f64) -> Result<Option<(String, sdf::Path)>, QueryError> {
self.cache
.clip_spec_site_in_set(self.graph, self.diagnostics, self.set, &self.query, time)
}
}
pub(crate) trait OpinionResolver {
fn on_site(&mut self, _site: &OpinionSite<'_>) -> Step {
Step::Continue
}
fn on_time_samples(&mut self, _samples: &sdf::TimeSampleMap, _site: &OpinionSite<'_>) -> Step {
Step::Continue
}
fn on_default(&mut self, _value: &sdf::Value, _site: &OpinionSite<'_>) -> Step {
Step::Continue
}
fn on_unresolved_samples(&mut self, _site: &OpinionSite<'_>) {}
fn on_withheld(&mut self, kind: Withheld, _site: &OpinionSite<'_>) -> Step {
match kind {
Withheld::DefaultBlock => Step::Stop,
Withheld::TimeSamplesFieldBlock => Step::Continue,
}
}
fn claims_sites(&self) -> bool {
true
}
fn on_clips(&mut self, _probe: &mut ClipProbe<'_>, _site: &OpinionSite<'_>) -> Result<Step, QueryError> {
Ok(Step::Continue)
}
}