Data Transformation & Pipeline
This walkthrough details how to use the pipeline components, dynamic mappers, and the Adapt trait to translate data representations securely across interfaces.
Compilable Example
//! Transformation example showcasing the Adapt trait, Pipeline, and FieldMapper. use adapters::{Adapt, Error, FieldMapper, Pipeline, Value}; use std::collections::BTreeMap; struct Celsius(f64); struct Fahrenheit(f64); impl Adapt<Celsius> for Fahrenheit { fn adapt(c: Celsius) -> Result<Self, Error> { Ok(Fahrenheit(c.0 * 9.0 / 5.0 + 32.0)) } } fn make_obj(fields: &[(&str, Value)]) -> Value { let mut m = BTreeMap::new(); for (k, v) in fields { m.insert(k.to_string(), v.clone()); } Value::Object(m) } fn main() -> Result<(), Box<dyn std::error::Error>> { println!("=== transformation example ===\n"); let f = Fahrenheit::adapt(Celsius(100.0))?; println!("100°C = {}°F", f.0); let pipeline = Pipeline::new() .step(|v| match v { Value::Int(n) => Ok(Value::Int(n * 2)), other => Ok(other), }) .step(|v| match v { Value::Int(n) => Ok(Value::Int(n + 10)), other => Ok(other), }); let result = pipeline.run(Value::Int(5))?; println!("Pipeline 5 → {}", result); let mapper = FieldMapper::new() .map("first_name", "firstName") .map("last_name", "lastName") .map("phone_number", "phoneNumber"); let db_row = make_obj(&[ ("first_name", Value::String("Alice".into())), ("last_name", Value::String("Smith".into())), ("phone_number", Value::String("+1-555-0100".into())), ("id", Value::Int(42)), ]); let api_response = mapper.apply(&db_row)?; println!("\nDB row: {}", db_row); println!("API response: {}", api_response); Ok(()) }