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}