vantage-dataset 0.6.1

Dataset traits for the Vantage data framework
Documentation
use async_trait::async_trait;
use indexmap::IndexMap;

use vantage_types::{Entity, TryFromRecord};

use crate::{
    im::ImTable,
    traits::{DataSet, ReadableDataSet, Result},
};
use vantage_core::util::error::vantage_error;

#[async_trait]
impl<E> DataSet<E> for ImTable<E> where E: Entity {}

#[async_trait]
impl<E> ReadableDataSet<E> for ImTable<E>
where
    E: Entity,
    <E as TryFromRecord<serde_json::Value>>::Error: std::fmt::Debug,
{
    async fn list(&self) -> Result<IndexMap<Self::Id, E>> {
        // Snapshot id+record pairs under the lock; convert outside it.
        let rows = self.data_source.with_table(&self.table_name, |table| {
            table
                .iter()
                .map(|(id, record)| (id.clone(), record.clone()))
                .collect::<Vec<_>>()
        });

        let mut records = IndexMap::new();
        for (id, record) in rows {
            // Add the id field to the record for conversion
            let mut record_with_id = record;
            record_with_id.insert("id".to_string(), serde_json::Value::String(id.clone()));

            let entity: E = E::try_from_record(&record_with_id)
                .map_err(|e| vantage_error!("Failed to convert record to entity: {:?}", e))?;
            records.insert(id, entity);
        }

        Ok(records)
    }

    async fn get(&self, id: impl Into<Self::Id> + Send) -> Result<Option<E>> {
        let id = id.into();

        let Some(record) = self
            .data_source
            .with_table(&self.table_name, |table| table.get(&id).cloned())
        else {
            return Ok(None);
        };

        let mut record_with_id = record;
        record_with_id.insert("id".to_string(), serde_json::Value::String(id.clone()));

        let entity = E::try_from_record(&record_with_id)
            .map_err(|e| vantage_error!("Failed to convert record to entity: {:?}", e))?;
        Ok(Some(entity))
    }

    async fn get_some(&self) -> Result<Option<(Self::Id, E)>> {
        let Some((id, record)) = self.data_source.with_table(&self.table_name, |table| {
            table
                .iter()
                .next()
                .map(|(id, record)| (id.clone(), record.clone()))
        }) else {
            return Ok(None);
        };

        // Add the id field to the record for conversion
        let mut record_with_id = record;
        record_with_id.insert("id".to_string(), serde_json::Value::String(id.clone()));

        let entity: E = E::try_from_record(&record_with_id)
            .map_err(|e| vantage_error!("Failed to convert record to entity: {:?}", e))?;
        Ok(Some((id, entity)))
    }
}

// Tests are in tests/im_dataset.rs integration tests