use std::{borrow::Cow, fmt::Debug};
use serde::{Deserialize, Serialize};
use crate::{document::Document, schema::Collection};
pub mod map;
pub use map::{Key, Map};
use super::collection;
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error("error deserializing document {0}")]
Serialization(#[from] serde_cbor::Error),
#[error("error serializing view keys {0}")]
KeySerialization(anyhow::Error),
#[error("reduce is unimplemented")]
ReduceUnimplemented,
}
pub type MapResult<K = (), V = ()> = Result<Option<Map<K, V>>, Error>;
pub trait View: Send + Sync + Debug + 'static {
type Collection: Collection;
type MapKey: Key + 'static;
type MapValue: Serialize + for<'de> Deserialize<'de>;
type Reduce: Serialize + for<'de> Deserialize<'de>;
fn version(&self) -> usize;
fn name(&self) -> Cow<'static, str>;
fn map(&self, document: &Document<'_>) -> MapResult<Self::MapKey, Self::MapValue>;
#[allow(unused_variables)]
fn reduce(
&self,
mappings: &[Map<Self::MapKey, Self::MapValue>],
rereduce: bool,
) -> Result<Self::Reduce, Error> {
Err(Error::ReduceUnimplemented)
}
}
pub enum SerializableValue<'a, T: Serialize> {
Owned(T),
Borrowed(&'a T),
}
impl<'a, T> From<&'a T> for SerializableValue<'a, T>
where
T: Serialize,
{
fn from(other: &'a T) -> SerializableValue<'a, T> {
SerializableValue::Borrowed(other)
}
}
impl<'a, T> AsRef<T> for SerializableValue<'a, T>
where
T: Serialize,
{
fn as_ref(&self) -> &T {
match self {
Self::Owned(value) => value,
Self::Borrowed(value) => value,
}
}
}
pub trait Serialized: Send + Sync + Debug {
fn collection(&self) -> collection::Id;
fn version(&self) -> usize;
fn name(&self) -> Cow<'static, str>;
fn map(&self, document: &Document<'_>) -> Result<Option<map::Serialized>, Error>;
}
impl<T> Serialized for T
where
T: View,
<T as View>::MapKey: 'static,
{
fn collection(&self) -> collection::Id {
<<Self as View>::Collection as Collection>::id()
}
fn version(&self) -> usize {
self.version()
}
fn name(&self) -> Cow<'static, str> {
self.name()
}
fn map(&self, document: &Document<'_>) -> Result<Option<map::Serialized>, Error> {
let map = self.map(document)?;
match map {
Some(map) => Ok(Some(map::Serialized {
source: map.source,
key: map
.key
.as_big_endian_bytes()
.map_err(Error::KeySerialization)?
.to_vec(),
value: serde_cbor::to_vec(&map.value)?,
})),
None => Ok(None),
}
}
}