Skip to main content

runtime/turn/wave/
closure.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4// Copyright (c) 2026 2youg1 and the sprawling contributors
5
6//! A closure as a tool face: it answers every call as it admits it and
7//! declares no effect, so its waves are serial.
8
9use kernel::{AxCode, AxError, TimeMs, Tool, ToolCall, ToolMeta, ToolOutcome};
10
11use super::{Admitted, ConcurrentInvoke};
12use crate::bench::Ticket;
13
14/// A closure is a tool face that answers every call as it admits it:
15/// it declares no effect, so its waves are serial. citysim and the tests
16/// that script a tool's answer drive a run through this one.
17impl<F> ConcurrentInvoke for F
18where
19    F: FnMut(&ToolCall, TimeMs) -> Result<ToolOutcome, AxError>,
20{
21    fn meta_of(&self, _call: &ToolCall) -> Option<&ToolMeta> {
22        None
23    }
24
25    fn admit(&mut self, call: &ToolCall, t: TimeMs) -> Admitted {
26        Admitted::Answered(self(call, t))
27    }
28
29    fn tool(&self, _ticket: &Ticket) -> Result<&dyn Tool, AxError> {
30        Err(unheld_ticket())
31    }
32
33    fn account(
34        &mut self,
35        _call: &ToolCall,
36        _ticket: Ticket,
37        _answered: Result<ToolOutcome, AxError>,
38    ) -> Result<ToolOutcome, AxError> {
39        Err(unheld_ticket())
40    }
41}
42
43fn unheld_ticket() -> AxError {
44    AxError::failure(
45        AxCode::ToolUnavailable,
46        "run a cleared tool call",
47        "a tool face that answers every call as it admits it was handed a ticket",
48    )
49    .with_recovery("report this against runtime::turn::wave: only a bench issues tickets")
50}