pub struct Speculation<R: StoryRng = FastRng> { /* private fields */ }Expand description
A sandboxed, self-contained speculative run over a story’s current state. See the module docs for the full picture.
Owns everything it needs to drive itself: an Arc-shared Program
(cheap to bump, never mutated), an owned clone of the source World
(read through, never written back), a Mode::Sandbox fork of the
source FlowLocal (where every write lands, and which is simply
dropped to discard them), and a clone of the source FlowInstance’s
current execution position. Dropping a Speculation is the entire
discard operation — nothing it did ever reached the state it was
forked from.
Implementations§
Source§impl<R: StoryRng> Speculation<R>
impl<R: StoryRng> Speculation<R>
Sourcepub fn fork_from(
program: Arc<Program>,
world: &World,
local: &FlowLocal,
flow: &FlowInstance,
line_tables: &[Vec<LineEntry>],
) -> Self
pub fn fork_from( program: Arc<Program>, world: &World, local: &FlowLocal, flow: &FlowInstance, line_tables: &[Vec<LineEntry>], ) -> Self
Fork a Speculation from an arbitrary flow’s current state.
This is the composable, flow-level constructor — bevy-brink (or any
other orchestration layer juggling multiple FlowInstances over
possibly-distinct Worlds) can call this directly for any flow,
not just a crate::Story’s default one. crate::Story::speculate
is a convenience wrapper over this for the common case.
world is cloned (an owned snapshot — the source World is never
touched again by this speculation), local is forked in
Mode::Sandbox (every unit routes Local; writes never reach
world or local’s own future writes), and flow is cloned to
capture the exact execution position to speculate from.
Sourcepub fn go_to_path(&mut self, path: &str) -> Result<(), RuntimeError>
pub fn go_to_path(&mut self, path: &str) -> Result<(), RuntimeError>
Move this speculation’s play head to a named knot/stitch path —
the speculative equivalent of FlowInstance::choose_path_string.
Only this speculation’s own (sandboxed) position moves; the flow it
was forked from is untouched.
§Errors
Same as FlowInstance::choose_path_string: an unknown path, a
jump while parked on an unresolved external, or a jump while a
function evaluation is in progress.
Sourcepub fn choose(&mut self, index: usize) -> Result<(), RuntimeError>
pub fn choose(&mut self, index: usize) -> Result<(), RuntimeError>
Select a pending choice by index — the speculative equivalent of
FlowInstance::choose.
§Errors
RuntimeError::NotWaitingForChoice if this speculation isn’t
waiting on a choice; RuntimeError::InvalidChoiceIndex for an
out-of-range index.
Sourcepub fn advance(
&mut self,
budget: Budget,
handler: &dyn ExternalFnHandler,
) -> Result<SpeculationStep, RuntimeError>
pub fn advance( &mut self, budget: Budget, handler: &dyn ExternalFnHandler, ) -> Result<SpeculationStep, RuntimeError>
Drive this speculation forward by one visible line, honoring
budget in place of the runtime’s hardcoded step/line ceilings.
Checks budget.lines against the running total of lines this
speculation has already produced before stepping — a speculation
that has already hit its line budget errors immediately rather
than stepping further. Otherwise drives exactly one visible line
(or a yield point) via FlowInstance::advance’s machinery,
capped at budget.steps VM steps instead of the production
1,000,000.
A deferred external (crate::ExternalResult::Pending) surfaces
as SpeculationStep::AwaitingExternal — resolve it via
resolve_external and call advance
again, exactly as FlowInstance::advance’s callers do.
§Errors
RuntimeError::LineLimitExceeded if budget.lines has already
been reached; RuntimeError::StepLimitExceeded if budget.steps
is exhausted before a line completes; any other error advance
itself can produce (e.g. RuntimeError::StoryEnded).
Sourcepub fn eval_function(
&mut self,
name: &str,
args: &[Value],
handler: &dyn ExternalFnHandler,
) -> Result<FunctionEval, RuntimeError>
pub fn eval_function( &mut self, name: &str, args: &[Value], handler: &dyn ExternalFnHandler, ) -> Result<FunctionEval, RuntimeError>
Evaluate an ink function on this speculation, returning its value —
the speculative equivalent of crate::Story::call_function /
FlowInstance::begin_function_eval. Output is isolated (as for
any engine→ink call) and, being on the sandboxed fork, can never
escape to the live story either way.
§Errors
RuntimeError::FunctionNotFound for an unknown name;
RuntimeError::ArgCountMismatch if args.len() doesn’t match the
function’s declared parameter count; any error
FlowInstance::begin_function_eval itself can produce.
Sourcepub fn resume_function_eval(
&mut self,
handler: &dyn ExternalFnHandler,
) -> Result<FunctionEval, RuntimeError>
pub fn resume_function_eval( &mut self, handler: &dyn ExternalFnHandler, ) -> Result<FunctionEval, RuntimeError>
Resume a function evaluation on this speculation that paused on
FunctionEval::AwaitingExternal, after the pending external has
been resolved via resolve_external —
the speculative equivalent of
FlowInstance::resume_function_eval.
Closes the F4.1 gap: eval_function could
pause on a deferred external with no way to continue. The full
cycle is eval_function → AwaitingExternal →
resolve_external(value) → resume_function_eval →
Returned(value).
§Errors
RuntimeError::NotEvaluatingFunction if no evaluation is in
progress on this speculation; any error
FlowInstance::resume_function_eval itself can produce.
Sourcepub fn resolve_external(&mut self, value: Value)
pub fn resolve_external(&mut self, value: Value)
Resolve a pending external call on this speculation by supplying
its return value. No-op if none is pending. See
FlowInstance::resolve_external.
Sourcepub fn pending_external_name(&self) -> Option<&str>
pub fn pending_external_name(&self) -> Option<&str>
The ink-declared name of the external this speculation is paused
on, if any. See FlowInstance::pending_external_name.
Sourcepub fn transcript(&self) -> &[OutputPart]
pub fn transcript(&self) -> &[OutputPart]
The append-only transcript of output parts produced by this
speculation so far — structural references, resolved against
whatever line tables the caller has (see
FlowInstance::transcript). Empty for a freshly-forked
speculation that hasn’t been driven yet.
Sourcepub fn rendered_transcript(&self) -> Vec<(String, Vec<String>)>
pub fn rendered_transcript(&self) -> Vec<(String, Vec<String>)>
transcript, resolved to (text, tags) pairs
against this speculation’s own program and line tables — the
read-facing sibling for callers (e.g. brink-web’s wasm binding) that
want rendered text rather than raw structural parts. Mirrors
crate::transcript::render_transcript.