use std::collections::BTreeMap;
use std::fmt::Debug;
use arc_bytes::serde::Bytes;
use serde::{Deserialize, Serialize};
use crate::document::{CollectionHeader, DocumentId, Header, OwnedDocument};
use crate::schema::view::{self, ByteSource, Key, SerializedView, View, ViewSchema};
use crate::schema::Collection;
#[derive(Eq, PartialEq, Debug)]
pub struct Map<K = (), V = ()> {
pub source: Header,
pub key: K,
pub value: V,
}
impl<K, V> Map<K, V> {
pub(crate) fn serialized<'a, View>(&self) -> Result<Serialized, view::Error>
where
K: Key<'a>,
View: SerializedView<Value = V>,
{
Ok(Serialized {
source: self.source.clone(),
key: Bytes::from(
self.key
.as_ord_bytes()
.map_err(view::Error::key_serialization)?
.to_vec(),
),
value: Bytes::from(View::serialize(&self.value)?),
})
}
}
impl<K, V> Map<K, V> {
pub const fn new(source: Header, key: K, value: V) -> Self {
Self { source, key, value }
}
}
#[derive(Eq, PartialEq, Debug)]
pub struct CollectionMap<PrimaryKey, K = (), V = ()> {
pub source: CollectionHeader<PrimaryKey>,
pub key: K,
pub value: V,
}
pub type ViewMappings<V> = Vec<
CollectionMap<
<<V as View>::Collection as Collection>::PrimaryKey,
<V as View>::Key,
<V as View>::Value,
>,
>;
#[derive(Debug, Eq, PartialEq)]
#[must_use]
pub enum Mappings<K = (), V = ()> {
Simple(Option<Map<K, V>>),
List(Vec<Map<K, V>>),
}
impl<K, V> Default for Mappings<K, V> {
fn default() -> Self {
Self::none()
}
}
impl<K, V> Mappings<K, V> {
pub const fn none() -> Self {
Self::Simple(None)
}
pub fn push(&mut self, mapping: Map<K, V>) {
match self {
Self::Simple(existing_mapping) => {
*self = if let Some(existing_mapping) = existing_mapping.take() {
Self::List(vec![existing_mapping, mapping])
} else {
Self::Simple(Some(mapping))
};
}
Self::List(vec) => vec.push(mapping),
}
}
pub fn and(mut self, mappings: Self) -> Self {
self.extend(mappings);
self
}
pub fn iter(&self) -> MappingsIter<'_, K, V> {
self.into_iter()
}
pub fn len(&self) -> usize {
match self {
Mappings::Simple(None) => 0,
Mappings::Simple(Some(_)) => 1,
Mappings::List(v) => v.len(),
}
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl<K, V> Extend<Map<K, V>> for Mappings<K, V> {
fn extend<T: IntoIterator<Item = Map<K, V>>>(&mut self, iter: T) {
let iter = iter.into_iter();
for map in iter {
self.push(map);
}
}
}
impl<K, V> FromIterator<Map<K, V>> for Mappings<K, V> {
fn from_iter<T: IntoIterator<Item = Map<K, V>>>(iter: T) -> Self {
let mut mappings = Self::none();
mappings.extend(iter);
mappings
}
}
impl<K, V> FromIterator<Self> for Mappings<K, V> {
fn from_iter<T: IntoIterator<Item = Self>>(iter: T) -> Self {
let mut iter = iter.into_iter();
if let Some(mut collected) = iter.next() {
for mappings in iter {
collected.extend(mappings);
}
collected
} else {
Self::none()
}
}
}
impl<K, V> IntoIterator for Mappings<K, V> {
type IntoIter = MappingsIntoIter<K, V>;
type Item = Map<K, V>;
fn into_iter(self) -> Self::IntoIter {
match self {
Mappings::Simple(option) => MappingsIntoIter::Inline(option),
Mappings::List(list) => MappingsIntoIter::Vec(list.into_iter()),
}
}
}
impl<'a, K, V> IntoIterator for &'a Mappings<K, V> {
type IntoIter = MappingsIter<'a, K, V>;
type Item = &'a Map<K, V>;
fn into_iter(self) -> Self::IntoIter {
match self {
Mappings::Simple(option) => MappingsIter::Inline(option.iter()),
Mappings::List(list) => MappingsIter::Vec(list.iter()),
}
}
}
pub enum MappingsIntoIter<K = (), V = ()> {
Inline(Option<Map<K, V>>),
Vec(std::vec::IntoIter<Map<K, V>>),
}
impl<K, V> Iterator for MappingsIntoIter<K, V> {
type Item = Map<K, V>;
fn next(&mut self) -> Option<Self::Item> {
match self {
MappingsIntoIter::Inline(opt) => opt.take(),
MappingsIntoIter::Vec(iter) => iter.next(),
}
}
}
pub enum MappingsIter<'a, K = (), V = ()> {
Inline(std::option::Iter<'a, Map<K, V>>),
Vec(std::slice::Iter<'a, Map<K, V>>),
}
impl<'a, K, V> Iterator for MappingsIter<'a, K, V> {
type Item = &'a Map<K, V>;
fn next(&mut self) -> Option<Self::Item> {
match self {
MappingsIter::Inline(i) => i.next(),
MappingsIter::Vec(i) => i.next(),
}
}
}
pub struct MappedDocuments<D, V: View> {
pub mappings: ViewMappings<V>,
pub documents: BTreeMap<<V::Collection as Collection>::PrimaryKey, D>,
}
impl<D, V: View> MappedDocuments<D, V> {
#[must_use]
pub fn len(&self) -> usize {
self.mappings.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[must_use]
#[allow(clippy::missing_panics_doc)]
pub fn get(&self, index: usize) -> Option<MappedDocument<'_, D, V::Key, V::Value>> {
if index < self.len() {
let mapping = &self.mappings[index];
let document = self
.documents
.get(&mapping.source.id)
.expect("missing mapped document");
Some(MappedDocument {
key: &mapping.key,
value: &mapping.value,
document,
})
} else {
None
}
}
#[must_use]
pub const fn iter(&self) -> MappedDocumentsIter<'_, D, V> {
MappedDocumentsIter {
docs: self,
index: 0,
}
}
}
impl<D, V: View> Debug for MappedDocuments<D, V>
where
V::Key: Debug,
V::Value: Debug,
D: Debug,
<V::Collection as Collection>::PrimaryKey: Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("MappedDocuments")
.field("mappings", &self.mappings)
.field("documents", &self.documents)
.finish()
}
}
pub struct MappedDocumentsIter<'a, D, V: View> {
docs: &'a MappedDocuments<D, V>,
index: usize,
}
impl<'a, D, V: View> IntoIterator for &'a MappedDocuments<D, V> {
type IntoIter = MappedDocumentsIter<'a, D, V>;
type Item = MappedDocument<'a, D, V::Key, V::Value>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, D, V: View> Iterator for MappedDocumentsIter<'a, D, V> {
type Item = MappedDocument<'a, D, V::Key, V::Value>;
fn next(&mut self) -> Option<Self::Item> {
let doc = self.docs.get(self.index);
self.index = self.index.saturating_add(1);
doc
}
}
pub struct MappedDocument<'a, D, K, V> {
pub key: &'a K,
pub value: &'a V,
pub document: &'a D,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Serialized {
pub source: Header,
pub key: Bytes,
pub value: Bytes,
}
impl Serialized {
pub fn deserialized<View: SerializedView>(
&self,
) -> Result<Map<View::Key, View::Value>, view::Error> {
Ok(Map::new(
self.source.clone(),
<View::Key as Key>::from_ord_bytes(ByteSource::Borrowed(&self.key))
.map_err(view::Error::key_serialization)?,
View::deserialize(&self.value)?,
))
}
}
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct MappedSerializedDocuments {
pub mappings: Vec<Serialized>,
pub documents: BTreeMap<DocumentId, OwnedDocument>,
}
impl MappedSerializedDocuments {
pub fn deserialized<View: SerializedView>(
self,
) -> Result<MappedDocuments<OwnedDocument, View>, crate::Error> {
let mappings = self
.mappings
.iter()
.map(|mapping| {
let deserialized = Serialized::deserialized::<View>(mapping)?;
Ok(CollectionMap {
source: deserialized.source.try_into()?,
key: deserialized.key,
value: deserialized.value,
})
})
.collect::<Result<Vec<_>, crate::Error>>()?;
Ok(MappedDocuments {
mappings,
documents: self
.documents
.into_iter()
.map(|(key, value)| {
let key = key.deserialize()?;
Ok((key, value))
})
.collect::<Result<BTreeMap<_, _>, crate::Error>>()?,
})
}
}
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct MappedValue<K, V> {
pub key: K,
pub value: V,
}
impl<K, V> MappedValue<K, V> {
pub const fn new(key: K, value: V) -> Self {
Self { key, value }
}
}
pub type ViewMappedValue<'doc, V> =
MappedValue<<V as ViewSchema>::MappedKey<'doc>, <<V as ViewSchema>::View as View>::Value>;
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct MappedSerializedValue {
pub key: Bytes,
pub value: Bytes,
}