///|
/// A pure adapter for a source such as a Smithy model. Implementations return
/// only render properties. `resolve` keeps all diagram structure and links.
pub(open) trait LinkSource {
participant(Self, Link) -> ParticipantProperties?
message(Self, Link) -> MessageProperties?
}
///|
/// A resolved model and warnings for targets absent from the source.
pub struct Resolution {
sequence : Sequence
diagnostics : ReadOnlyArray[@diagrams.Diagnostic]
}
///|
/// Resolve links without changing the input or allowing the source to replace
/// participants, events, labels, numbering or links. Existing properties remain
/// when a source does not know a target.
pub fn[S : LinkSource] resolve(sequence : Sequence, source : S) -> Resolution {
let diagnostics = []
fn missing(link : Link) {
diagnostics.push(@diagrams.Diagnostic::warning(
"sequence/unresolved-link", "No source item for \{link.target}",
))
}
let participants = sequence.participants.map(p => {
match p.link {
Some(link) => match source.participant(link) {
Some(properties) => p.with_properties(properties)
None => { missing(link); p }
}
None => p
}
})
fn events(items : ReadOnlyArray[Event]) -> ReadOnlyArray[Event] {
items.map(e => match e {
Message(m) => match m.link {
Some(link) => match source.message(link) {
Some(properties) => Message(m.with_properties(properties))
None => { missing(link); e }
}
None => e
}
Frame(f) => Frame({ ..f, sections: f.sections.map(s => { ..s, events: events(s.events) }) })
_ => e
})
}
let resolved = { ..sequence, participants, events: events(sequence.events) }
{ sequence: resolved, diagnostics: ReadOnlyArray::from_array(diagnostics) }
}