use std::sync::Arc;
use crate::column::Value;
use crate::error::Result;
use crate::query::EventKey;
use crate::series::{ColumnDef, TimeSeries};
use super::buffer::EventBuffer;
use super::event::{LiveEvent, LiveSchema};
use super::reduce::Place;
pub(crate) type Step = Box<dyn FnMut(&LiveEvent) -> Option<Kept> + Send>;
pub(crate) enum Kept {
Pass(LiveEvent),
New(Vec<Option<Value>>),
}
#[derive(Debug, Clone, Copy)]
pub(crate) enum Window {
Rows(usize),
Span(i64),
}
pub struct LiveView {
pub(crate) name: String,
pub(crate) schema: Arc<LiveSchema>,
pub(crate) buffer: EventBuffer,
pub(crate) step: Step,
pub(crate) window: Option<Window>,
pub(crate) window_ms: Option<i64>,
}
impl std::fmt::Debug for LiveView {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("LiveView")
.field("name", &self.name)
.field("len", &self.buffer.len())
.finish_non_exhaustive()
}
}
impl LiveView {
pub(crate) fn new(
name: String,
schema: Arc<LiveSchema>,
step: Step,
history: impl Iterator<Item = LiveEvent>,
window: Option<Window>,
window_ms: Option<i64>,
) -> Self {
let mut view = Self {
name,
buffer: EventBuffer::new(Arc::clone(&schema)),
schema,
step,
window,
window_ms,
};
for event in history {
match (view.step)(&event) {
Some(Kept::Pass(kept)) => view.buffer.insert_owned(kept),
Some(Kept::New(values)) => view.buffer.insert_cells(event.key().clone(), values),
None => continue,
};
}
view.trim();
view
}
pub(crate) fn take(
&mut self,
event: &LiveEvent,
hand_on: bool,
) -> Option<(Option<LiveEvent>, Place)> {
let kept = match (self.step)(event)? {
Kept::Pass(kept) => kept,
Kept::New(values) if hand_on => {
LiveEvent::new(Arc::clone(&self.schema), event.key().clone(), values)
}
Kept::New(values) => {
let at = self.buffer.insert_cells(event.key().clone(), values);
return Some((None, Place { at }));
}
};
if hand_on {
let at = self.buffer.insert(&kept);
Some((Some(kept), Place { at }))
} else {
Some((
None,
Place {
at: self.buffer.insert_owned(kept),
},
))
}
}
fn trim(&mut self) {
let n = self.excess();
if n > 0 {
self.buffer.evict(n, false);
}
}
pub(crate) fn excess(&self) -> usize {
match self.window {
None => 0,
Some(Window::Rows(keep)) => self.buffer.len().saturating_sub(keep),
Some(Window::Span(ms)) => match self.buffer.back_begin() {
None => 0,
Some(last) => self.buffer.count_before(last.saturating_sub(ms)),
},
}
}
pub(crate) fn drop_front(&mut self, n: usize) {
self.buffer.evict(n, false);
}
pub(crate) fn mirror_evict(&mut self, n: usize, keep: bool) -> (i64, Vec<LiveEvent>) {
let last = self.buffer.begin_at(n - 1);
(last, self.buffer.evict(n, keep))
}
pub fn name(&self) -> &str {
&self.name
}
pub fn schema(&self) -> &[ColumnDef] {
&self.schema.columns
}
pub fn len(&self) -> usize {
self.buffer.len()
}
pub fn count(&self) -> usize {
self.buffer.len()
}
pub fn event_rate(&self) -> Result<f64> {
let ms = self
.window_ms
.ok_or_else(|| crate::error::PondError::InvalidData {
call: "LiveView::event_rate",
message: "needs a time window: build the view with window(duration) first \
(a window of rows has no length in time)"
.into(),
})?;
Ok(self.buffer.len() as f64 / (ms as f64 / 1000.0))
}
pub fn is_empty(&self) -> bool {
self.buffer.len() == 0
}
pub fn at(&self, index: i64) -> Option<LiveEvent> {
self.buffer.at(index)
}
pub fn first(&self) -> Option<LiveEvent> {
self.buffer.at(0)
}
pub fn last(&self) -> Option<LiveEvent> {
self.buffer.at(-1)
}
pub fn events(&self) -> impl ExactSizeIterator<Item = LiveEvent> + '_ {
self.buffer.iter()
}
pub fn bisect(&self, key: impl Into<EventKey>) -> usize {
self.buffer.bisect(&key.into())
}
pub fn includes_key(&self, key: impl Into<EventKey>) -> bool {
self.buffer.includes_key(&key.into())
}
pub fn at_or_before(&self, key: impl Into<EventKey>) -> Option<LiveEvent> {
self.buffer.at_or_before(&key.into())
}
pub fn at_or_after(&self, key: impl Into<EventKey>) -> Option<LiveEvent> {
self.buffer.at_or_after(&key.into())
}
pub fn find(&self, mut test: impl FnMut(&LiveEvent) -> bool) -> Option<LiveEvent> {
self.buffer.iter().find(|e| test(e))
}
pub fn some(&self, mut test: impl FnMut(&LiveEvent) -> bool) -> bool {
self.buffer.iter().any(|e| test(&e))
}
pub fn every(&self, mut test: impl FnMut(&LiveEvent) -> bool) -> bool {
self.buffer.iter().all(|e| test(&e))
}
pub fn to_time_series(&self) -> Result<TimeSeries> {
self.buffer.snapshot("LiveView::to_time_series", &self.name)
}
}