Skip to main content

kibana_object_manager/etl/
transform.rs

1//! Transformer trait for data transformation
2
3use eyre::Result;
4
5/// Transformer trait for transforming data items
6///
7/// Implementors define how to transform items:
8/// - Data cleaning (removing fields)
9/// - Data enrichment (adding fields)
10/// - Format conversion
11/// - Validation
12///
13/// # Example
14/// ```no_run
15/// use kibana_object_manager::etl::Transformer;
16/// use eyre::Result;
17///
18/// struct FieldDropper {
19///     fields: Vec<String>,
20/// }
21///
22/// impl Transformer for FieldDropper {
23///     type Input = serde_json::Value;
24///     type Output = serde_json::Value;
25///     
26///     fn transform(&self, mut input: Self::Input) -> Result<Self::Output> {
27///         if let Some(obj) = input.as_object_mut() {
28///             for field in &self.fields {
29///                 obj.remove(field);
30///             }
31///         }
32///         Ok(input)
33///     }
34/// }
35/// ```
36pub trait Transformer: Send + Sync {
37    /// Input item type
38    type Input: Send;
39
40    /// Output item type after transformation
41    type Output: Send;
42
43    /// Transform a single item
44    ///
45    /// # Errors
46    /// Returns an error if transformation fails (validation, conversion, etc.)
47    fn transform(&self, input: Self::Input) -> Result<Self::Output>;
48
49    /// Transform multiple items (default batch implementation)
50    ///
51    /// Override this for optimized batch processing
52    fn transform_many(&self, inputs: Vec<Self::Input>) -> Result<Vec<Self::Output>> {
53        inputs.into_iter().map(|i| self.transform(i)).collect()
54    }
55}
56
57/// Identity transformer that passes items through unchanged
58///
59/// Use this when you need a transformer but don't want to modify the data.
60/// The generic parameter T must be specified when creating the transformer.
61pub struct IdentityTransformer<T> {
62    _phantom: std::marker::PhantomData<T>,
63}
64
65impl<T> Default for IdentityTransformer<T> {
66    fn default() -> Self {
67        Self {
68            _phantom: std::marker::PhantomData,
69        }
70    }
71}
72
73impl<T> IdentityTransformer<T> {
74    pub fn new() -> Self {
75        Self::default()
76    }
77}
78
79impl<T: Send + Sync> Transformer for IdentityTransformer<T> {
80    type Input = T;
81    type Output = T;
82
83    fn transform(&self, input: Self::Input) -> Result<Self::Output> {
84        Ok(input)
85    }
86}
87
88#[cfg(test)]
89mod tests {
90    use super::*;
91
92    #[test]
93    fn test_identity_transformer() {
94        let transformer = IdentityTransformer::<i32>::new();
95        let input = vec![1, 2, 3];
96        let output = transformer.transform_many(input.clone()).unwrap();
97        assert_eq!(input, output);
98    }
99}