use derive_more::Display; use mule::{Dataset, DatasetValue, Parsed, RawValue, ReadingOptions, Result, Typer}; use std::env; #[tokio::main] pub async fn main() -> Result<()> { let file_path = env::args() .skip(1) .next() .unwrap_or_else(|| "datasets/sales-10.tsv".to_string()); let options = ReadingOptions::default(); let typer = CustomTyper::default(); let dataset = Dataset::read_file(file_path, options, &typer).await?; println!("Got dataset: {:#?}", dataset); Ok(()) } #[derive(Clone, PartialEq, Debug)] pub enum CustomValue { Maybe(YayNay), Int(i64), Float(f64), Text(String), } impl DatasetValue for CustomValue { fn get_column_type(&self) -> CustomColumnType { match self { CustomValue::Maybe(_) => CustomColumnType::Maybe, CustomValue::Int(_) => CustomColumnType::Int, CustomValue::Float(_) => CustomColumnType::Float, CustomValue::Text(_) => CustomColumnType::Text, } } } #[derive(PartialEq, Debug, Eq, Hash, Clone, Copy)] pub enum YayNay { Yay, Nay, Nah, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Display)] pub enum CustomColumnType { Maybe, Int, Float, Text, Unknown, } impl Default for CustomColumnType { fn default() -> Self { CustomColumnType::Unknown } } #[derive(Default, Debug, Clone)] pub struct CustomTyper; impl CustomTyper { fn as_int(&self, value: &RawValue) -> Parsed { value.parse_i64().map(CustomValue::Int) } fn as_float(&self, value: &RawValue) -> Parsed { value.parse_f64().map(CustomValue::Float) } fn as_text(&self, value: &RawValue) -> CustomValue { CustomValue::Text(value.0.to_string()) } fn as_maybe(&self, value: &RawValue) -> Parsed { match value.0.to_lowercase().trim() { "" => Parsed::Missing, "yay" => Parsed::Some(CustomValue::Maybe(YayNay::Yay)), "nay" => Parsed::Some(CustomValue::Maybe(YayNay::Nay)), _ => Parsed::Invalid, } } } impl Typer for CustomTyper { type ColumnType = CustomColumnType; type DatasetValue = CustomValue; const COLUMN_TYPES: &'static [Self::ColumnType] = &[ CustomColumnType::Maybe, CustomColumnType::Int, CustomColumnType::Float, CustomColumnType::Text, ]; fn parse_as(&self, value: &RawValue, tag: Self::ColumnType) -> Parsed { match tag { CustomColumnType::Maybe => self.as_maybe(value), CustomColumnType::Int => self.as_int(value), CustomColumnType::Float => self.as_float(value), CustomColumnType::Text => Parsed::Some(self.as_text(value)), CustomColumnType::Unknown => Parsed::Invalid, } } }