iguazu 0.0.1

Tools for viewing, storing, and sharing mixed-signal time series data
Documentation
use std::{any::Any, pin::Pin, sync::Arc};

use async_executor::Executor;
use futures_lite::AsyncWriteExt;
use url::Url;

use crate::{io::{RelativePath, WritableFile}, schema::{json_virtual::StreamRef, EntityStream}, stream::ArcStream};
use super::ExportError;

pub(crate) fn export(_executor: Arc<Executor<'static>>, entity: EntityStream, file: Box<dyn WritableFile>) -> Pin<Box<dyn Future<Output=Result<(), ExportError>> + Send>> {
    Box::pin(async move {
        let url = file.url()
            .ok_or_else(|| ExportError::InvalidFile(format!("Cannot get URL of output file")))?;
        let contents = entity.try_map_data(&mut |stream| stream_ref(stream, &url))?;
        let json = serde_json::to_string(&contents).unwrap();

        let mut writer = file.writer().await?;
        writer.write_all(json.as_bytes()).await?;
        writer.flush().await?;

        Ok(())
    })
}

fn stream_ref(stream: &ArcStream, base: &Url) -> Result<StreamRef, ExportError> {
    if let Some(stream) = (&**stream as &dyn Any).downcast_ref::<crate::storage::FlatFileStream>() {
        let url = stream.url()
            .ok_or_else(|| ExportError::UnsupportedStream(format!("Stream has no URL")))?;
        let relative = RelativePath::from_base(base, &url)
            .ok_or_else(|| ExportError::UnsupportedStream(format!("Stream from `{url}` is not relative to `{base}`")))?;
        Ok(StreamRef::FlatFile {
            file_name: relative,
            element_size: stream.element_size(),
            offset: stream.offset(),
            count: stream.count(),
        })
    } else {
        Err(ExportError::UnsupportedStream(format!("Stream `{:?}` is not supported in Virtual export", stream)))
    }
}