Skip to main content

tenferro_runtime/runtime/
extension_provider.rs

1use std::any::Any;
2use std::fmt;
3use std::hash::Hasher;
4
5use tenferro_ops::ext_op::ExtensionOp;
6
7use super::{
8    ExecutionContextIdentity, HardwareClassId, InputSignature, PrepareCapability, PrepareError,
9    PrepareOptionsKey, PreparedOperationBinding, ResolvedPlanningConfig, ResolvedProgramPlacement,
10    SpecializationProjection,
11};
12
13/// Snapshot-retained extension planning configuration.
14///
15/// The family id follows the existing extension `&'static str` contract used by
16/// [`ExtensionOp::family_id`].
17pub trait ExtensionPlanningConfig: Any + fmt::Debug + Send + Sync + 'static {
18    /// Return the extension family id this configuration belongs to.
19    fn family_id(&self) -> &'static str;
20    /// Return this config as [`Any`] for typed equality checks.
21    fn as_any(&self) -> &dyn Any;
22    /// Hash only the family-specific payload.
23    fn payload_hash(&self, state: &mut dyn Hasher);
24    /// Compare only the family-specific payload.
25    fn payload_eq(&self, other: &dyn ExtensionPlanningConfig) -> bool;
26    /// Return logical retained bytes owned by this config.
27    fn retained_bytes(&self) -> usize;
28}
29
30/// Runtime-created borrowed extension preparation request.
31pub struct ExtensionPrepareRequest<'a> {
32    operation: &'a dyn ExtensionOp,
33    binding: &'a PreparedOperationBinding,
34    resolved_placement: &'a ResolvedProgramPlacement,
35    hardware_class: &'a HardwareClassId,
36    planning: &'a ResolvedPlanningConfig,
37    extension_config: &'a dyn ExtensionPlanningConfig,
38    inputs: &'a InputSignature,
39    prepare_options_key: &'a PrepareOptionsKey,
40    specialization: &'a SpecializationProjection,
41}
42
43impl<'a> ExtensionPrepareRequest<'a> {
44    #[allow(dead_code)]
45    #[allow(clippy::too_many_arguments)]
46    pub(crate) fn new(
47        operation: &'a dyn ExtensionOp,
48        binding: &'a PreparedOperationBinding,
49        resolved_placement: &'a ResolvedProgramPlacement,
50        hardware_class: &'a HardwareClassId,
51        planning: &'a ResolvedPlanningConfig,
52        extension_config: &'a dyn ExtensionPlanningConfig,
53        inputs: &'a InputSignature,
54        prepare_options_key: &'a PrepareOptionsKey,
55        specialization: &'a SpecializationProjection,
56    ) -> Self {
57        Self {
58            operation,
59            binding,
60            resolved_placement,
61            hardware_class,
62            planning,
63            extension_config,
64            inputs,
65            prepare_options_key,
66            specialization,
67        }
68    }
69
70    /// Return the extension operation payload.
71    pub fn operation(&self) -> &'a dyn ExtensionOp {
72        self.operation
73    }
74
75    /// Return the runtime-created binding.
76    pub fn binding(&self) -> &'a PreparedOperationBinding {
77        self.binding
78    }
79
80    /// Return the selected program placement.
81    pub fn resolved_placement(&self) -> &'a ResolvedProgramPlacement {
82        self.resolved_placement
83    }
84
85    /// Return the selected hardware class.
86    pub fn hardware_class(&self) -> &'a HardwareClassId {
87        self.hardware_class
88    }
89
90    /// Return resolved planning policy.
91    pub fn planning(&self) -> &'a ResolvedPlanningConfig {
92        self.planning
93    }
94
95    /// Return the snapshot-retained extension planning config.
96    pub fn extension_config(&self) -> &'a dyn ExtensionPlanningConfig {
97        self.extension_config
98    }
99
100    /// Return value-free input metadata.
101    pub fn inputs(&self) -> &'a InputSignature {
102        self.inputs
103    }
104
105    /// Return the normalized prepare-options key.
106    pub fn prepare_options_key(&self) -> &'a PrepareOptionsKey {
107        self.prepare_options_key
108    }
109
110    /// Return the concrete specialization projection.
111    pub fn specialization(&self) -> &'a SpecializationProjection {
112        self.specialization
113    }
114}
115
116impl fmt::Debug for ExtensionPrepareRequest<'_> {
117    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
118        formatter
119            .debug_struct("ExtensionPrepareRequest")
120            .field("operation", &self.operation.family_id())
121            .field("binding", self.binding)
122            .field("resolved_placement", self.resolved_placement)
123            .field("hardware_class", self.hardware_class)
124            .field("planning", self.planning)
125            .field("extension_config", &self.extension_config.family_id())
126            .field("inputs", &self.inputs.entries().len())
127            .field("prepare_options_key", self.prepare_options_key)
128            .field("specialization", self.specialization)
129            .finish()
130    }
131}
132
133/// Preparation provider for one extension family.
134pub trait ExtensionEngine: fmt::Debug + Send + Sync + 'static {
135    /// Return the extension family id handled by this engine.
136    fn family_id(&self) -> &'static str;
137    /// Return the runtime engine id used by this provider.
138    fn engine_id(&self) -> &super::EngineId;
139    /// Return the execution-context type identity needed by this provider.
140    fn context_identity(&self) -> ExecutionContextIdentity;
141    /// Prepare an extension operation.
142    ///
143    /// # Errors
144    ///
145    /// Returns [`PrepareError`] when provider preparation fails.
146    fn prepare(
147        &self,
148        request: ExtensionPrepareRequest<'_>,
149    ) -> Result<PrepareCapability, PrepareError>;
150}