use futures::{Stream, StreamExt};
use polars::prelude::*;
use crate::error::ClientError;
use crate::event::Event;
pub async fn events_to_dataframe<S>(mut events: S) -> Result<DataFrame, PolarsError>
where
S: Stream<Item = Result<Event, ClientError>> + Unpin,
{
let mut event_ids: Vec<String> = Vec::new();
let mut times: Vec<i64> = Vec::new();
let mut sources: Vec<String> = Vec::new();
let mut subjects: Vec<String> = Vec::new();
let mut types: Vec<String> = Vec::new();
let mut data: Vec<String> = Vec::new();
let mut spec_versions: Vec<String> = Vec::new();
let mut data_content_types: Vec<String> = Vec::new();
let mut predecessor_hashes: Vec<String> = Vec::new();
let mut hashes: Vec<String> = Vec::new();
let mut trace_parents: Vec<Option<String>> = Vec::new();
let mut trace_states: Vec<Option<String>> = Vec::new();
let mut signatures: Vec<Option<String>> = Vec::new();
while let Some(result) = events.next().await {
let event = result
.map_err(|e| PolarsError::ComputeError(format!("Failed to read event: {e}").into()))?;
event_ids.push(event.id().to_string());
times.push(event.time().timestamp_millis());
sources.push(event.source().to_string());
subjects.push(event.subject().to_string());
types.push(event.ty().to_string());
data.push(event.data().to_string());
spec_versions.push(event.specversion().to_string());
data_content_types.push(event.datacontenttype().to_string());
predecessor_hashes.push(event.predecessorhash().to_string());
hashes.push(event.hash().to_string());
trace_parents.push(event.traceparent().map(ToString::to_string));
trace_states.push(event.tracestate().map(ToString::to_string));
signatures.push(event.signature().map(ToString::to_string));
}
DataFrame::new(vec![
Column::new("event_id".into(), event_ids),
Column::new("time".into(), times)
.cast(&DataType::Datetime(TimeUnit::Milliseconds, None))?,
Column::new("source".into(), sources),
Column::new("subject".into(), subjects),
Column::new("type".into(), types),
Column::new("data".into(), data),
Column::new("spec_version".into(), spec_versions),
Column::new("data_content_type".into(), data_content_types),
Column::new("predecessor_hash".into(), predecessor_hashes),
Column::new("hash".into(), hashes),
Column::new("trace_parent".into(), trace_parents),
Column::new("trace_state".into(), trace_states),
Column::new("signature".into(), signatures),
])
}