use std::pin::Pin;
use async_trait::async_trait;
use ciborium::Value as CborValue;
use futures_core::Stream;
use indexmap::IndexMap;
use vantage_core::{Result, VantageError, error};
use vantage_types::Record;
use crate::{capabilities::VistaCapabilities, vista::Vista};
#[async_trait]
#[allow(clippy::ptr_arg)]
pub trait TableShell: Send + Sync + 'static {
async fn list_vista_values(&self, vista: &Vista)
-> Result<IndexMap<String, Record<CborValue>>>;
async fn get_vista_value(
&self,
vista: &Vista,
id: &String,
) -> Result<Option<Record<CborValue>>>;
async fn get_vista_some_value(
&self,
vista: &Vista,
) -> Result<Option<(String, Record<CborValue>)>>;
#[allow(clippy::type_complexity)]
fn stream_vista_values<'a>(
&'a self,
vista: &'a Vista,
) -> Pin<Box<dyn Stream<Item = Result<(String, Record<CborValue>)>> + Send + 'a>>
where
Self: Sync,
{
Box::pin(async_stream::stream! {
match self.list_vista_values(vista).await {
Ok(map) => {
for item in map {
yield Ok(item);
}
}
Err(e) => yield Err(e),
}
})
}
async fn insert_vista_value(
&self,
vista: &Vista,
_id: &String,
_record: &Record<CborValue>,
) -> Result<Record<CborValue>> {
Err(self.default_error("insert_vista_value", "can_insert", vista))
}
async fn replace_vista_value(
&self,
vista: &Vista,
_id: &String,
_record: &Record<CborValue>,
) -> Result<Record<CborValue>> {
Err(self.default_error("replace_vista_value", "can_update", vista))
}
async fn patch_vista_value(
&self,
vista: &Vista,
_id: &String,
_partial: &Record<CborValue>,
) -> Result<Record<CborValue>> {
Err(self.default_error("patch_vista_value", "can_update", vista))
}
async fn delete_vista_value(&self, vista: &Vista, _id: &String) -> Result<()> {
Err(self.default_error("delete_vista_value", "can_delete", vista))
}
async fn delete_vista_all_values(&self, vista: &Vista) -> Result<()> {
Err(self.default_error("delete_vista_all_values", "can_delete", vista))
}
async fn insert_vista_return_id_value(
&self,
vista: &Vista,
_record: &Record<CborValue>,
) -> Result<String> {
Err(self.default_error("insert_vista_return_id_value", "can_insert", vista))
}
async fn get_vista_count(&self, vista: &Vista) -> Result<i64> {
Ok(self.list_vista_values(vista).await?.len() as i64)
}
fn add_eq_condition(&mut self, _field: &str, _value: &CborValue) -> Result<()> {
Err(error!(
format!(
"add_eq_condition not implemented for '{}'",
std::any::type_name::<Self>()
),
method = "add_eq_condition",
source_type = std::any::type_name::<Self>()
)
.is_unimplemented())
}
fn driver_name(&self) -> &'static str {
"unknown"
}
fn capabilities(&self) -> &VistaCapabilities;
fn capability_flag(&self, name: &str) -> bool {
let caps = self.capabilities();
match name {
"can_count" => caps.can_count,
"can_insert" => caps.can_insert,
"can_update" => caps.can_update,
"can_delete" => caps.can_delete,
"can_subscribe" => caps.can_subscribe,
"can_invalidate" => caps.can_invalidate,
_ => false,
}
}
fn default_error(&self, method: &str, capability: &str, vista: &Vista) -> VantageError {
let source_type = std::any::type_name::<Self>();
let vista_name = vista.name().to_string();
if self.capability_flag(capability) {
error!(
format!(
"'{}' is advertised as VistaCapability for '{}' but implementation for '{}' is missing",
capability, source_type, method
),
method = method,
capability = capability,
source_type = source_type,
vista_name = vista_name
)
.is_unimplemented()
} else {
error!(
format!(
"'{}' is not supported by '{}'; '{}' refused",
capability, source_type, method
),
method = method,
capability = capability,
source_type = source_type,
vista_name = vista_name
)
.is_unsupported()
}
}
}