vortex_array/aggregate_fn/plugin.rs
1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4use std::sync::Arc;
5
6use vortex_error::VortexResult;
7use vortex_session::VortexSession;
8
9use crate::aggregate_fn::AggregateFn;
10use crate::aggregate_fn::AggregateFnId;
11use crate::aggregate_fn::AggregateFnRef;
12use crate::aggregate_fn::AggregateFnVTable;
13use crate::dtype::DType;
14
15/// Reference-counted pointer to an aggregate function plugin.
16pub type AggregateFnPluginRef = Arc<dyn AggregateFnPlugin>;
17
18/// Registry trait for ID-based deserialization of aggregate functions.
19///
20/// Plugins are registered in the session by their [`AggregateFnId`]. When a serialized aggregate
21/// function is encountered, the session resolves the ID to the plugin and calls [`deserialize`]
22/// to reconstruct the value as an [`AggregateFnRef`].
23///
24/// [`deserialize`]: AggregateFnPlugin::deserialize
25pub trait AggregateFnPlugin: 'static + Send + Sync {
26 /// Returns the ID for this aggregate function.
27 fn id(&self) -> AggregateFnId;
28
29 /// Deserialize an aggregate function from serialized metadata.
30 fn deserialize(&self, metadata: &[u8], session: &VortexSession)
31 -> VortexResult<AggregateFnRef>;
32
33 /// The default zone statistic (per-chunk) for a column of `input_dtype`, or `None` if the
34 /// dtype is not supported (or this aggregate is not a zone statistic at all).
35 ///
36 /// This is how a registered aggregate volunteers itself as a per-chunk statistic: when a
37 /// zoned layout writer opens a column, it collects every plugin's default via
38 /// [`AggregateFnSession::zone_stat_defaults`], so new statistics can be added without the
39 /// writer knowing about them.
40 ///
41 /// [`AggregateFnSession::zone_stat_defaults`]: crate::aggregate_fn::session::AggregateFnSession::zone_stat_defaults
42 fn zone_stat_default(&self, _input_dtype: &DType) -> Option<AggregateFnRef> {
43 None
44 }
45}
46
47impl std::fmt::Debug for dyn AggregateFnPlugin {
48 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49 f.debug_tuple("AggregateFnPlugin")
50 .field(&self.id())
51 .finish()
52 }
53}
54
55impl<V: AggregateFnVTable> AggregateFnPlugin for V {
56 fn id(&self) -> AggregateFnId {
57 AggregateFnVTable::id(self)
58 }
59
60 fn deserialize(
61 &self,
62 metadata: &[u8],
63 session: &VortexSession,
64 ) -> VortexResult<AggregateFnRef> {
65 let options = AggregateFnVTable::deserialize(self, metadata, session)?;
66 Ok(AggregateFn::new(self.clone(), options).erased())
67 }
68
69 fn zone_stat_default(&self, input_dtype: &DType) -> Option<AggregateFnRef> {
70 AggregateFnVTable::zone_stat_default(self, input_dtype)
71 }
72}