use std::sync::Arc;
use pedant_types::{ResolutionRecord, ResolutionReport, SymbolDefinition, SymbolReference};
use crate::error::GraphBuildError;
use crate::id::{GraphNodeId, index_of, position};
use crate::node::GraphNodeKind;
use crate::reference::GraphReferenceKind;
use super::draft::{
DefinitionProjection, FragmentSlot, ProjectionPlan, ReferenceProjection, UnitPlan,
};
use super::placement::{DefinitionIdentity, DefinitionTable, SourceIdentity, SourceSet};
use super::state::{ProjectionState, SourceScope};
pub(crate) fn matching_fingerprint<Fingerprint: PartialEq>(
snapshot: Fingerprint,
stated: Fingerprint,
) -> Result<(), GraphBuildError> {
match snapshot == stated {
true => Ok(()),
false => Err(GraphBuildError::SnapshotFingerprintMismatch),
}
}
pub(crate) fn bound_instance<Instance>(
held: Option<Instance>,
unit: u32,
) -> Result<Instance, GraphBuildError> {
held.ok_or(GraphBuildError::DanglingUnitBinding { unit })
}
pub(crate) fn distinct_binding(held: Option<u32>, unit: u32) -> Result<(), GraphBuildError> {
match held {
None => Ok(()),
Some(held) => Err(GraphBuildError::SharedUnitBinding { held, unit }),
}
}
pub(crate) fn dependency_unit(
bound: Option<u32>,
stated: (u32, &str),
) -> Result<u32, GraphBuildError> {
let (edge, alias) = stated;
bound.ok_or_else(|| GraphBuildError::MissingDependencyUnit {
edge,
alias: Box::from(alias),
})
}
pub(crate) fn distinct_source(
held: Option<u32>,
unit: u32,
path: &str,
) -> Result<(), GraphBuildError> {
match held {
None => Ok(()),
Some(_) => Err(GraphBuildError::RepeatedUnitSource {
unit,
path: Box::from(path),
}),
}
}
pub(crate) fn planned_unit(units: &[UnitPlan], unit: u32) -> Result<&UnitPlan, GraphBuildError> {
units
.get(index_of(unit))
.ok_or(GraphBuildError::MissingUnitBinding { unit })
}
pub(crate) fn instantiated_source<'a>(
sources: &'a SourceSet,
unit: u32,
path: &str,
) -> Result<(u32, &'a SourceIdentity), GraphBuildError> {
sources
.locate(unit, path)
.ok_or_else(|| GraphBuildError::MissingSourceNode {
unit,
path: Box::from(path),
})
}
pub(crate) fn definition_identity(
table: &DefinitionTable,
definition: u32,
) -> Result<&Arc<DefinitionIdentity>, GraphBuildError> {
table
.identity(definition)
.ok_or(GraphBuildError::MissingDefinitionNode { definition })
}
pub(crate) fn optional_identity(
table: &DefinitionTable,
stated: Option<u32>,
) -> Result<Option<Arc<DefinitionIdentity>>, GraphBuildError> {
match stated {
None => Ok(None),
Some(at) => Ok(Some(Arc::clone(definition_identity(table, at)?))),
}
}
pub(crate) fn stated_definition_kind(
named: Option<GraphNodeKind>,
definition: &SymbolDefinition,
) -> Result<GraphNodeKind, GraphBuildError> {
named.ok_or(GraphBuildError::UnnamedDefinitionKind {
definition: definition.id().index(),
})
}
pub(crate) fn stated_reference_kind(
named: Option<GraphReferenceKind>,
reference: &SymbolReference,
) -> Result<GraphReferenceKind, GraphBuildError> {
named.ok_or(GraphBuildError::UnnamedReferenceKind {
reference: reference.id().index(),
})
}
pub(crate) fn definition_fragment(
table: &DefinitionTable,
definition: u32,
) -> Result<u32, GraphBuildError> {
table
.fragment(definition)
.ok_or(GraphBuildError::MissingDefinitionNode { definition })
}
pub(crate) fn placed_slot(
slot: Option<FragmentSlot>,
unit: u32,
path: &str,
) -> Result<FragmentSlot, GraphBuildError> {
slot.ok_or_else(|| GraphBuildError::MissingSourceNode {
unit,
path: Box::from(path),
})
}
pub(crate) fn resolved_references(
report: &ResolutionReport,
) -> Result<Box<[(&SymbolReference, &ResolutionRecord)]>, GraphBuildError> {
let references = report.references();
let records = report.resolutions();
match references.len() == records.len() {
true => Ok(references.iter().zip(records).collect()),
false => Err(GraphBuildError::ReferenceRecordMismatch {
references: position(references.len()),
records: position(records.len()),
}),
}
}
pub(crate) fn planned_definition(
plan: &ProjectionPlan,
at: FragmentSlot,
definition: u32,
) -> Result<&DefinitionProjection, GraphBuildError> {
plan.definition(at)
.ok_or(GraphBuildError::MissingDefinitionNode { definition })
}
pub(crate) fn planned_reference(
plan: &ProjectionPlan,
at: FragmentSlot,
reference: u32,
) -> Result<&ReferenceProjection, GraphBuildError> {
plan.reference(at)
.ok_or(GraphBuildError::MissingReferenceRecord { reference })
}
pub(crate) fn fragment_source(
plan: &ProjectionPlan,
fragment: u32,
definition: u32,
) -> Result<&SourceIdentity, GraphBuildError> {
plan.source(fragment)
.ok_or(GraphBuildError::MissingDefinitionNode { definition })
}
pub(crate) fn fragment_unit(plan: &ProjectionPlan, fragment: u32) -> Result<u32, GraphBuildError> {
plan.placed(fragment)
.map(|placed| placed.unit)
.ok_or(GraphBuildError::MissingUnitBinding { unit: fragment })
}
pub(crate) fn stated_definition(
plan: &ProjectionPlan,
definition: u32,
) -> Result<FragmentSlot, GraphBuildError> {
plan.definitions
.get(index_of(definition))
.copied()
.ok_or(GraphBuildError::MissingDefinitionNode { definition })
}
pub(crate) fn unit_slot<Slot>(
held: Option<&mut Slot>,
unit: u32,
) -> Result<&mut Slot, GraphBuildError> {
held.ok_or(GraphBuildError::MissingUnitBinding { unit })
}
pub(crate) fn unbound_container(
held: Option<GraphNodeId>,
unit: u32,
) -> Result<(), GraphBuildError> {
match held {
None => Ok(()),
Some(held) => Err(GraphBuildError::RepeatedUnitContainer {
unit,
container: held.index(),
}),
}
}
pub(crate) fn unit_scope(
held: Option<&mut SourceScope>,
unit: u32,
) -> Result<&mut SourceScope, GraphBuildError> {
held.ok_or(GraphBuildError::MissingUnitBinding { unit })
}
pub(crate) fn unit_container(
state: &ProjectionState,
unit: u32,
) -> Result<GraphNodeId, GraphBuildError> {
state
.container(unit)
.ok_or(GraphBuildError::MissingUnitBinding { unit })
}
pub(crate) fn source_node(
held: Option<GraphNodeId>,
unit: u32,
path: &str,
) -> Result<GraphNodeId, GraphBuildError> {
held.ok_or_else(|| GraphBuildError::MissingSourceNode {
unit,
path: Box::from(path),
})
}
pub(crate) fn definition_node(
state: &ProjectionState,
identity: &DefinitionIdentity,
stated: u32,
) -> Result<GraphNodeId, GraphBuildError> {
state
.definition(identity)
.ok_or(GraphBuildError::MissingDefinitionNode { definition: stated })
}