use crate::SheetPortError;
use crate::binding::ManifestBindings;
use crate::runtime::{EvalOptions, SheetPort};
use crate::value::{InputSnapshot, InputUpdate, OutputSnapshot};
use formualizer_eval::engine::RecalcPlan;
use formualizer_workbook::Workbook;
use sheetport_spec::Manifest;
pub struct SheetPortSession {
workbook: Workbook,
bindings: ManifestBindings,
}
impl SheetPortSession {
pub fn new(mut workbook: Workbook, manifest: Manifest) -> Result<Self, SheetPortError> {
let sheetport = SheetPort::new(&mut workbook, manifest)?;
let (_, bindings) = sheetport.into_parts();
Ok(Self { workbook, bindings })
}
pub fn from_parts(
mut workbook: Workbook,
bindings: ManifestBindings,
) -> Result<Self, SheetPortError> {
let sheetport = SheetPort::from_bindings(&mut workbook, bindings)?;
let (_, bindings) = sheetport.into_parts();
Ok(Self { workbook, bindings })
}
pub fn workbook(&self) -> &Workbook {
&self.workbook
}
pub fn workbook_mut(&mut self) -> &mut Workbook {
&mut self.workbook
}
pub fn manifest(&self) -> &Manifest {
self.bindings.manifest()
}
pub fn bindings(&self) -> &[crate::binding::PortBinding] {
self.bindings.bindings()
}
pub fn into_parts(self) -> (Workbook, ManifestBindings) {
(self.workbook, self.bindings)
}
fn with_sheetport<T>(
&mut self,
f: impl FnOnce(&mut SheetPort<'_>) -> Result<T, SheetPortError>,
) -> Result<T, SheetPortError> {
let bindings_clone = self.bindings.clone();
let mut sheetport = SheetPort::from_bindings(&mut self.workbook, bindings_clone)?;
let result = f(&mut sheetport)?;
let (_, bindings) = sheetport.into_parts();
self.bindings = bindings;
Ok(result)
}
pub fn read_inputs(&mut self) -> Result<InputSnapshot, SheetPortError> {
self.with_sheetport(|sp| sp.read_inputs())
}
pub fn read_outputs(&mut self) -> Result<OutputSnapshot, SheetPortError> {
self.with_sheetport(|sp| sp.read_outputs())
}
pub fn write_inputs(&mut self, update: InputUpdate) -> Result<(), SheetPortError> {
self.with_sheetport(|sp| sp.write_inputs(update))
}
pub fn evaluate_once(
&mut self,
options: EvalOptions,
) -> Result<OutputSnapshot, SheetPortError> {
self.with_sheetport(move |sp| sp.evaluate_once(options))
}
pub fn evaluate_with_plan(
&mut self,
plan: &RecalcPlan,
options: EvalOptions,
) -> Result<OutputSnapshot, SheetPortError> {
self.with_sheetport(move |sp| sp.evaluate_with_plan(plan, options))
}
}