1use crate::engine::range_view::RangeView;
2pub use crate::function::Function;
3use crate::interpreter::Interpreter;
4use crate::reference::CellRef;
5use formualizer_common::{
6 LiteralValue,
7 error::{ExcelError, ExcelErrorKind},
8};
9use std::any::Any;
10use std::borrow::Cow;
11use std::fmt::Debug;
12use std::sync::Arc;
13
14use formualizer_parse::parser::{ASTNode, ASTNodeType, ReferenceType, TableSpecifier};
15
16pub trait Range: Debug + Send + Sync {
19 fn get(&self, row: usize, col: usize) -> Result<LiteralValue, ExcelError>;
20 fn dimensions(&self) -> (usize, usize);
21
22 fn is_sparse(&self) -> bool {
23 false
24 }
25
26 fn is_infinite(&self) -> bool {
28 false
29 }
30
31 fn materialise(&self) -> Cow<'_, [Vec<LiteralValue>]> {
32 Cow::Owned(
33 (0..self.dimensions().0)
34 .map(|r| {
35 (0..self.dimensions().1)
36 .map(|c| self.get(r, c).unwrap_or(LiteralValue::Empty))
37 .collect()
38 })
39 .collect(),
40 )
41 }
42
43 fn iter_cells<'a>(&'a self) -> Box<dyn Iterator<Item = LiteralValue> + 'a> {
44 let (rows, cols) = self.dimensions();
45 Box::new((0..rows).flat_map(move |r| (0..cols).map(move |c| self.get(r, c).unwrap())))
46 }
47 fn iter_rows<'a>(&'a self) -> Box<dyn Iterator<Item = Vec<LiteralValue>> + 'a> {
48 let (rows, cols) = self.dimensions();
49 Box::new((0..rows).map(move |r| (0..cols).map(|c| self.get(r, c).unwrap()).collect()))
50 }
51
52 fn as_any(&self) -> &dyn Any;
54}
55
56impl Range for Box<dyn Range> {
58 fn get(&self, r: usize, c: usize) -> Result<LiteralValue, ExcelError> {
59 (**self).get(r, c)
60 }
61 fn dimensions(&self) -> (usize, usize) {
62 (**self).dimensions()
63 }
64 fn is_sparse(&self) -> bool {
65 (**self).is_sparse()
66 }
67 fn materialise(&self) -> Cow<'_, [Vec<LiteralValue>]> {
68 (**self).materialise()
69 }
70 fn iter_cells<'a>(&'a self) -> Box<dyn Iterator<Item = LiteralValue> + 'a> {
71 (**self).iter_cells()
72 }
73 fn iter_rows<'a>(&'a self) -> Box<dyn Iterator<Item = Vec<LiteralValue>> + 'a> {
74 (**self).iter_rows()
75 }
76 fn as_any(&self) -> &dyn Any {
77 (**self).as_any()
78 }
79}
80
81pub type CowValue<'a> = Cow<'a, LiteralValue>;
84
85pub enum EvaluatedArg<'a> {
86 LiteralValue(CowValue<'a>),
87 Range(Box<dyn Range>),
88}
89
90pub struct ArgumentHandle<'a, 'b> {
91 node: &'a ASTNode,
92 interp: &'a Interpreter<'b>,
93}
94
95impl<'a, 'b> ArgumentHandle<'a, 'b> {
96 pub(crate) fn new(node: &'a ASTNode, interp: &'a Interpreter<'b>) -> Self {
97 Self { node, interp }
98 }
99
100 pub fn value(&self) -> Result<CowValue<'_>, ExcelError> {
101 if let ASTNodeType::Literal(ref v) = self.node.node_type {
102 return Ok(Cow::Borrowed(v));
103 }
104 self.interp.evaluate_ast(self.node).map(Cow::Owned)
105 }
106
107 pub fn range(&self) -> Result<Box<dyn Range>, ExcelError> {
108 match &self.node.node_type {
109 ASTNodeType::Reference { reference, .. } => {
110 self.interp.context.resolve_range_like(reference)
111 }
112 ASTNodeType::Array(rows) => {
113 let mut materialized = Vec::new();
114 for row in rows {
115 let mut materialized_row = Vec::new();
116 for cell in row {
117 materialized_row.push(self.interp.evaluate_ast(cell)?);
118 }
119 materialized.push(materialized_row);
120 }
121 Ok(Box::new(InMemoryRange::new(materialized)))
122 }
123 _ => Err(ExcelError::new(ExcelErrorKind::Ref)
124 .with_message(format!("Expected a range, got {:?}", self.node.node_type))),
125 }
126 }
127
128 pub fn range_view(&self) -> Result<RangeView<'_>, ExcelError> {
130 match &self.node.node_type {
131 ASTNodeType::Reference { reference, .. } => self
132 .interp
133 .context
134 .resolve_range_view(reference, self.interp.current_sheet()),
135 ASTNodeType::Literal(formualizer_common::LiteralValue::Array(arr)) => {
137 Ok(RangeView::from_borrowed(&arr[..]))
139 }
140 ASTNodeType::Array(rows) => {
141 let mut out: Vec<Vec<LiteralValue>> = Vec::with_capacity(rows.len());
143 for r in rows {
144 let mut row_vals = Vec::with_capacity(r.len());
145 for cell in r {
146 row_vals.push(self.interp.evaluate_ast(cell)?);
147 }
148 out.push(row_vals);
149 }
150 Ok(RangeView::from_borrowed(Box::leak(Box::new(out))))
151 }
152 _ => Err(ExcelError::new(ExcelErrorKind::Ref)
153 .with_message("Argument cannot be interpreted as a range.")),
154 }
155 }
156
157 pub fn value_or_range(&self) -> Result<EvaluatedArg<'_>, ExcelError> {
158 self.range()
159 .map(EvaluatedArg::Range)
160 .or_else(|_| self.value().map(EvaluatedArg::LiteralValue))
161 }
162
163 pub fn lazy_values_owned(
168 &'a self,
169 ) -> Result<Box<dyn Iterator<Item = LiteralValue> + 'a>, ExcelError> {
170 match &self.node.node_type {
171 ASTNodeType::Reference { .. } => {
172 let view = self.range_view()?;
173 let mut values: Vec<LiteralValue> = Vec::new();
174 view.for_each_cell(&mut |v| {
175 values.push(v.clone());
176 Ok(())
177 })?;
178 Ok(Box::new(values.into_iter()))
179 }
180 ASTNodeType::Array(rows) => {
181 struct ArrayEvalIter<'a, 'b> {
182 rows: &'a [Vec<ASTNode>],
183 r: usize,
184 c: usize,
185 interp: &'a Interpreter<'b>,
186 }
187 impl<'a, 'b> Iterator for ArrayEvalIter<'a, 'b> {
188 type Item = LiteralValue;
189 fn next(&mut self) -> Option<Self::Item> {
190 if self.rows.is_empty() {
191 return None;
192 }
193 let rows = self.rows;
194 let mut r = self.r;
195 let mut c = self.c;
196 if r >= rows.len() {
197 return None;
198 }
199 let node = &rows[r][c];
200 c += 1;
202 if c >= rows[r].len() {
203 r += 1;
204 c = 0;
205 }
206 self.r = r;
207 self.c = c;
208 match self.interp.evaluate_ast(node) {
209 Ok(v) => Some(v),
210 Err(e) => Some(LiteralValue::Error(e)),
211 }
212 }
213 }
214 let it = ArrayEvalIter {
215 rows,
216 r: 0,
217 c: 0,
218 interp: self.interp,
219 };
220 Ok(Box::new(it))
221 }
222 _ => {
223 let v = self.value()?.into_owned();
225 Ok(Box::new(std::iter::once(v)))
226 }
227 }
228 }
229
230 pub fn ast(&self) -> &'a ASTNode {
231 self.node
232 }
233
234 pub fn as_reference(&self) -> Result<&'a ReferenceType, ExcelError> {
237 match &self.node.node_type {
238 ASTNodeType::Reference { reference, .. } => Ok(reference),
239 _ => Err(ExcelError::new(ExcelErrorKind::Ref)
240 .with_message("Expected a reference (by-ref argument)")),
241 }
242 }
243
244 pub fn as_reference_or_eval(&self) -> Result<ReferenceType, ExcelError> {
247 match &self.node.node_type {
248 ASTNodeType::Reference { reference, .. } => Ok(reference.clone()),
249 ASTNodeType::Function { name, args } => {
250 if let Some(fun) = self.interp.context.get_function("", name) {
251 let handles: Vec<ArgumentHandle> = args
252 .iter()
253 .map(|n| ArgumentHandle::new(n, self.interp))
254 .collect();
255 let fctx =
256 crate::traits::DefaultFunctionContext::new(self.interp.context, None);
257 if let Some(res) = fun.eval_reference(&handles, &fctx) {
258 res
259 } else {
260 Err(ExcelError::new(ExcelErrorKind::Ref)
261 .with_message("Function does not return a reference"))
262 }
263 } else {
264 Err(ExcelError::new(ExcelErrorKind::Name))
265 }
266 }
267 _ => {
268 Err(ExcelError::new(ExcelErrorKind::Ref)
269 .with_message("Argument is not a reference"))
270 }
271 }
272 }
273
274 pub fn matches_kind(&self, k: formualizer_common::ArgKind) -> Result<bool, ExcelError> {
276 Ok(match k {
277 formualizer_common::ArgKind::Any => true,
278 formualizer_common::ArgKind::Range => self.range().is_ok(),
279 formualizer_common::ArgKind::Number => matches!(
280 self.value()?.as_ref(),
281 LiteralValue::Number(_) | LiteralValue::Int(_)
282 ),
283 formualizer_common::ArgKind::Text => {
284 matches!(self.value()?.as_ref(), LiteralValue::Text(_))
285 }
286 formualizer_common::ArgKind::Logical => {
287 matches!(self.value()?.as_ref(), LiteralValue::Boolean(_))
288 }
289 })
290 }
291}
292
293#[derive(Debug, Clone)]
295pub struct InMemoryRange {
296 data: Vec<Vec<LiteralValue>>,
297}
298impl InMemoryRange {
299 pub fn new(d: Vec<Vec<LiteralValue>>) -> Self {
300 Self { data: d }
301 }
302}
303impl Range for InMemoryRange {
304 fn get(&self, r: usize, c: usize) -> Result<LiteralValue, ExcelError> {
305 Ok(self
306 .data
307 .get(r)
308 .and_then(|row| row.get(c))
309 .cloned()
310 .unwrap_or(LiteralValue::Empty))
311 }
312 fn dimensions(&self) -> (usize, usize) {
313 (self.data.len(), self.data.first().map_or(0, |r| r.len()))
314 }
315 fn as_any(&self) -> &dyn Any {
316 self
317 }
318}
319
320pub trait Table: Debug + Send + Sync {
323 fn get_cell(&self, row: usize, column: &str) -> Result<LiteralValue, ExcelError>;
324 fn get_column(&self, column: &str) -> Result<Box<dyn Range>, ExcelError>;
325 fn columns(&self) -> Vec<String> {
327 vec![]
328 }
329 fn data_height(&self) -> usize {
331 0
332 }
333 fn has_headers(&self) -> bool {
335 false
336 }
337 fn has_totals(&self) -> bool {
339 false
340 }
341 fn headers_row(&self) -> Option<Box<dyn Range>> {
343 None
344 }
345 fn totals_row(&self) -> Option<Box<dyn Range>> {
347 None
348 }
349 fn data_body(&self) -> Option<Box<dyn Range>> {
351 None
352 }
353 fn clone_box(&self) -> Box<dyn Table>;
354}
355impl Table for Box<dyn Table> {
356 fn get_cell(&self, r: usize, c: &str) -> Result<LiteralValue, ExcelError> {
357 (**self).get_cell(r, c)
358 }
359 fn get_column(&self, c: &str) -> Result<Box<dyn Range>, ExcelError> {
360 (**self).get_column(c)
361 }
362 fn columns(&self) -> Vec<String> {
363 (**self).columns()
364 }
365 fn data_height(&self) -> usize {
366 (**self).data_height()
367 }
368 fn has_headers(&self) -> bool {
369 (**self).has_headers()
370 }
371 fn has_totals(&self) -> bool {
372 (**self).has_totals()
373 }
374 fn headers_row(&self) -> Option<Box<dyn Range>> {
375 (**self).headers_row()
376 }
377 fn totals_row(&self) -> Option<Box<dyn Range>> {
378 (**self).totals_row()
379 }
380 fn data_body(&self) -> Option<Box<dyn Range>> {
381 (**self).data_body()
382 }
383 fn clone_box(&self) -> Box<dyn Table> {
384 (**self).clone_box()
385 }
386}
387
388pub trait ReferenceResolver: Send + Sync {
391 fn resolve_cell_reference(
392 &self,
393 sheet: Option<&str>,
394 row: u32,
395 col: u32,
396 ) -> Result<LiteralValue, ExcelError>;
397}
398pub trait RangeResolver: Send + Sync {
399 fn resolve_range_reference(
400 &self,
401 sheet: Option<&str>,
402 sr: Option<u32>,
403 sc: Option<u32>,
404 er: Option<u32>,
405 ec: Option<u32>,
406 ) -> Result<Box<dyn Range>, ExcelError>;
407}
408pub trait NamedRangeResolver: Send + Sync {
409 fn resolve_named_range_reference(
410 &self,
411 name: &str,
412 ) -> Result<Vec<Vec<LiteralValue>>, ExcelError>;
413}
414pub trait TableResolver: Send + Sync {
415 fn resolve_table_reference(
416 &self,
417 tref: &formualizer_parse::parser::TableReference,
418 ) -> Result<Box<dyn Table>, ExcelError>;
419}
420pub trait Resolver: ReferenceResolver + RangeResolver + NamedRangeResolver + TableResolver {
421 fn resolve_range_like(&self, r: &ReferenceType) -> Result<Box<dyn Range>, ExcelError> {
422 match r {
423 ReferenceType::Range {
424 sheet,
425 start_row,
426 start_col,
427 end_row,
428 end_col,
429 } => self.resolve_range_reference(
430 sheet.as_deref(),
431 *start_row,
432 *start_col,
433 *end_row,
434 *end_col,
435 ),
436 ReferenceType::Table(tref) => {
437 let t = self.resolve_table_reference(tref)?;
438 match &tref.specifier {
439 Some(TableSpecifier::Column(c)) => t.get_column(c),
440 Some(TableSpecifier::ColumnRange(start, end)) => {
441 let cols = t.columns();
443 let start_idx = cols.iter().position(|n| n.eq_ignore_ascii_case(start));
444 let end_idx = cols.iter().position(|n| n.eq_ignore_ascii_case(end));
445 if let (Some(mut si), Some(mut ei)) = (start_idx, end_idx) {
446 if si > ei {
447 std::mem::swap(&mut si, &mut ei);
448 }
449 let h = t.data_height();
451 let w = ei - si + 1;
452 let mut rows = vec![vec![LiteralValue::Empty; w]; h];
453 for (offset, ci) in (si..=ei).enumerate() {
454 let cname = &cols[ci];
455 let col_range = t.get_column(cname)?;
456 let (rh, _) = col_range.dimensions();
457 for (r, row) in rows.iter_mut().enumerate().take(h.min(rh)) {
458 row[offset] = col_range.get(r, 0)?;
459 }
460 }
461 Ok(Box::new(InMemoryRange::new(rows)))
462 } else {
463 Err(ExcelError::new(ExcelErrorKind::Ref).with_message(
464 "Column range refers to unknown column(s)".to_string(),
465 ))
466 }
467 }
468 Some(TableSpecifier::SpecialItem(
469 formualizer_parse::parser::SpecialItem::Headers,
470 )) => {
471 if let Some(h) = t.headers_row() {
472 Ok(h)
473 } else {
474 Ok(Box::new(InMemoryRange::new(vec![])))
475 }
476 }
477 Some(TableSpecifier::SpecialItem(
478 formualizer_parse::parser::SpecialItem::Totals,
479 )) => {
480 if let Some(tr) = t.totals_row() {
481 Ok(tr)
482 } else {
483 Ok(Box::new(InMemoryRange::new(vec![])))
484 }
485 }
486 Some(TableSpecifier::SpecialItem(
487 formualizer_parse::parser::SpecialItem::Data,
488 )) => {
489 if let Some(body) = t.data_body() {
490 Ok(body)
491 } else {
492 Ok(Box::new(InMemoryRange::new(vec![])))
493 }
494 }
495 Some(TableSpecifier::SpecialItem(
496 formualizer_parse::parser::SpecialItem::All,
497 )) => {
498 let mut out: Vec<Vec<LiteralValue>> = Vec::new();
500 if let Some(h) = t.headers_row() {
501 out.extend(h.iter_rows());
502 }
503 if let Some(body) = t.data_body() {
504 out.extend(body.iter_rows());
505 }
506 if let Some(tr) = t.totals_row() {
507 out.extend(tr.iter_rows());
508 }
509 Ok(Box::new(InMemoryRange::new(out)))
510 }
511 Some(TableSpecifier::SpecialItem(
512 formualizer_parse::parser::SpecialItem::ThisRow,
513 )) => Err(ExcelError::new(ExcelErrorKind::NImpl).with_message(
514 "@ (This Row) requires table-aware context; not yet supported".to_string(),
515 )),
516 Some(TableSpecifier::All) => {
517 let mut out: Vec<Vec<LiteralValue>> = Vec::new();
519 if let Some(h) = t.headers_row() {
520 out.extend(h.iter_rows());
521 }
522 if let Some(body) = t.data_body() {
523 out.extend(body.iter_rows());
524 }
525 if let Some(tr) = t.totals_row() {
526 out.extend(tr.iter_rows());
527 }
528 Ok(Box::new(InMemoryRange::new(out)))
529 }
530 Some(TableSpecifier::Data) => {
531 if let Some(body) = t.data_body() {
532 Ok(body)
533 } else {
534 Ok(Box::new(InMemoryRange::new(vec![])))
535 }
536 }
537 Some(TableSpecifier::Combination(_)) => Err(ExcelError::new(
539 ExcelErrorKind::NImpl,
540 )
541 .with_message("Complex structured references not yet supported".to_string())),
542 Some(TableSpecifier::Row(_)) => Err(ExcelError::new(ExcelErrorKind::NImpl)
543 .with_message("Row selectors (@/index) not yet supported".to_string())),
544 Some(TableSpecifier::Headers) | Some(TableSpecifier::Totals) => {
545 Err(ExcelError::new(ExcelErrorKind::NImpl).with_message(
546 "Legacy Headers/Totals variants not used; use SpecialItem".to_string(),
547 ))
548 }
549 None => Err(ExcelError::new(ExcelErrorKind::Ref).with_message(
550 "Table reference without specifier is unsupported".to_string(),
551 )),
552 }
553 }
554 ReferenceType::NamedRange(n) => {
555 let v = self.resolve_named_range_reference(n)?;
556 Ok(Box::new(InMemoryRange::new(v)))
557 }
558 ReferenceType::Cell { sheet, row, col } => {
559 let v = self.resolve_cell_reference(sheet.as_deref(), *row, *col)?;
560 Ok(Box::new(InMemoryRange::new(vec![vec![v]])))
561 }
562 }
563 }
564}
565
566pub trait FunctionProvider: Send + Sync {
569 fn get_function(&self, ns: &str, name: &str) -> Option<Arc<dyn Function>>;
570}
571
572pub trait EvaluationContext: Resolver + FunctionProvider {
573 fn thread_pool(&self) -> Option<&Arc<rayon::ThreadPool>> {
576 None
577 }
578
579 fn cancellation_token(&self) -> Option<&std::sync::atomic::AtomicBool> {
581 None
582 }
583
584 fn chunk_hint(&self) -> Option<usize> {
586 None
587 }
588
589 fn resolve_range_view<'c>(
592 &'c self,
593 _reference: &ReferenceType,
594 _current_sheet: &str,
595 ) -> Result<RangeView<'c>, ExcelError> {
596 Err(ExcelError::new(ExcelErrorKind::NImpl))
597 }
598
599 fn locale(&self) -> crate::locale::Locale {
601 crate::locale::Locale::invariant()
602 }
603
604 fn timezone(&self) -> &crate::timezone::TimeZoneSpec {
608 static DEFAULT_TZ: std::sync::OnceLock<crate::timezone::TimeZoneSpec> =
610 std::sync::OnceLock::new();
611 DEFAULT_TZ.get_or_init(crate::timezone::TimeZoneSpec::default)
612 }
613
614 fn volatile_level(&self) -> VolatileLevel {
616 VolatileLevel::Always
617 }
618
619 fn workbook_seed(&self) -> u64 {
621 0xF0F0_D0D0_AAAA_5555
622 }
623
624 fn recalc_epoch(&self) -> u64 {
626 0
627 }
628
629 fn used_rows_for_columns(
634 &self,
635 _sheet: &str,
636 _start_col: u32,
637 _end_col: u32,
638 ) -> Option<(u32, u32)> {
639 None
640 }
641
642 fn used_cols_for_rows(
645 &self,
646 _sheet: &str,
647 _start_row: u32,
648 _end_row: u32,
649 ) -> Option<(u32, u32)> {
650 None
651 }
652
653 fn sheet_bounds(&self, _sheet: &str) -> Option<(u32, u32)> {
655 None
656 }
657
658 fn data_snapshot_id(&self) -> u64 {
660 0
661 }
662
663 fn backend_caps(&self) -> BackendCaps {
665 BackendCaps::default()
666 }
667
668 fn arrow_fastpath_enabled(&self) -> bool {
673 false
674 }
675
676 fn date_system(&self) -> crate::engine::DateSystem {
679 crate::engine::DateSystem::Excel1900
680 }
681
682 fn build_criteria_mask(
685 &self,
686 _view: &crate::arrow_store::ArrowRangeView<'_>,
687 _col_in_view: usize,
688 _pred: &crate::args::CriteriaPredicate,
689 ) -> Option<std::sync::Arc<arrow_array::BooleanArray>> {
690 None
691 }
692}
693
694#[derive(Copy, Clone, Debug, Default)]
696pub struct BackendCaps {
697 pub streaming: bool,
699 pub used_region: bool,
701 pub write: bool,
703 pub tables: bool,
705 pub async_stream: bool,
707}
708
709#[derive(Copy, Clone, Debug, Eq, PartialEq)]
712pub enum VolatileLevel {
713 Always,
715 OnRecalc,
717 OnOpen,
719}
720
721pub trait FunctionContext {
723 fn locale(&self) -> crate::locale::Locale;
724 fn timezone(&self) -> &crate::timezone::TimeZoneSpec;
725 fn thread_pool(&self) -> Option<&std::sync::Arc<rayon::ThreadPool>>;
726 fn cancellation_token(&self) -> Option<&std::sync::atomic::AtomicBool>;
727 fn chunk_hint(&self) -> Option<usize>;
728
729 fn volatile_level(&self) -> VolatileLevel;
730 fn workbook_seed(&self) -> u64;
731 fn recalc_epoch(&self) -> u64;
732 fn current_cell(&self) -> Option<CellRef>;
733
734 fn resolve_range_view<'c>(
736 &'c self,
737 _reference: &ReferenceType,
738 _current_sheet: &str,
739 ) -> Result<RangeView<'c>, ExcelError> {
740 Err(ExcelError::new(ExcelErrorKind::NImpl))
741 }
742
743 fn get_or_build_mask(&self, _key: &str) -> Option<crate::engine::masks::DenseMask> {
748 None
749 }
750
751 fn rng_for_current(&self, fn_salt: u64) -> rand::rngs::SmallRng {
753 use crate::rng::{compose_seed, small_rng_from_lanes};
754 let (sheet_id, row, col) = self
755 .current_cell()
756 .map(|c| (c.sheet_id as u32, c.coord.row, c.coord.col))
757 .unwrap_or((0, 0, 0));
758 let epoch = match self.volatile_level() {
760 VolatileLevel::OnRecalc => self.recalc_epoch(),
761 _ => 0,
762 };
763 let (l0, l1) = compose_seed(self.workbook_seed(), sheet_id, row, col, fn_salt, epoch);
764 small_rng_from_lanes(l0, l1)
765 }
766
767 fn arrow_fastpath_enabled(&self) -> bool {
769 false
770 }
771
772 fn date_system(&self) -> crate::engine::DateSystem {
774 crate::engine::DateSystem::Excel1900
775 }
776
777 fn get_criteria_mask(
780 &self,
781 _view: &crate::arrow_store::ArrowRangeView<'_>,
782 _col_in_view: usize,
783 _pred: &crate::args::CriteriaPredicate,
784 ) -> Option<std::sync::Arc<arrow_array::BooleanArray>> {
785 None
786 }
787}
788
789pub struct DefaultFunctionContext<'a> {
791 pub base: &'a dyn EvaluationContext,
792 pub current: Option<CellRef>,
793}
794
795impl<'a> DefaultFunctionContext<'a> {
796 pub fn new(base: &'a dyn EvaluationContext, current: Option<CellRef>) -> Self {
797 Self { base, current }
798 }
799}
800
801impl<'a> FunctionContext for DefaultFunctionContext<'a> {
802 fn locale(&self) -> crate::locale::Locale {
803 self.base.locale()
804 }
805 fn timezone(&self) -> &crate::timezone::TimeZoneSpec {
806 self.base.timezone()
807 }
808 fn thread_pool(&self) -> Option<&std::sync::Arc<rayon::ThreadPool>> {
809 self.base.thread_pool()
810 }
811 fn cancellation_token(&self) -> Option<&std::sync::atomic::AtomicBool> {
812 self.base.cancellation_token()
813 }
814 fn chunk_hint(&self) -> Option<usize> {
815 self.base.chunk_hint()
816 }
817
818 fn volatile_level(&self) -> VolatileLevel {
819 self.base.volatile_level()
820 }
821 fn workbook_seed(&self) -> u64 {
822 self.base.workbook_seed()
823 }
824 fn recalc_epoch(&self) -> u64 {
825 self.base.recalc_epoch()
826 }
827 fn current_cell(&self) -> Option<CellRef> {
828 self.current
829 }
830
831 fn resolve_range_view<'c>(
832 &'c self,
833 reference: &ReferenceType,
834 current_sheet: &str,
835 ) -> Result<RangeView<'c>, ExcelError> {
836 self.base.resolve_range_view(reference, current_sheet)
837 }
838
839 fn arrow_fastpath_enabled(&self) -> bool {
842 self.base.arrow_fastpath_enabled()
843 }
844
845 fn date_system(&self) -> crate::engine::DateSystem {
846 self.base.date_system()
847 }
848
849 fn get_criteria_mask(
850 &self,
851 view: &crate::arrow_store::ArrowRangeView<'_>,
852 col_in_view: usize,
853 pred: &crate::args::CriteriaPredicate,
854 ) -> Option<std::sync::Arc<arrow_array::BooleanArray>> {
855 self.base.build_criteria_mask(view, col_in_view, pred)
856 }
857}