Lines
87.29 %
Functions
59.15 %
Branches
100 %
use std::fmt::{Display, Write};
use serde::{Deserialize, Serialize};
use crate::document::{BorrowedDocument, CollectionDocument, DocumentId, OwnedDocument, Revision};
use crate::key::Key;
use crate::schema::view::map::Mappings;
use crate::schema::{Map, SerializedCollection};
/// The header of a `Document`.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
pub struct Header {
/// The id of the Document. Unique across the collection the document is
/// contained within.
pub id: DocumentId,
/// The revision of the stored document.
pub revision: Revision,
}
/// A type that can return a [`Header`].
pub trait HasHeader {
/// Returns the header for this instance.
fn header(&self) -> Result<Header, crate::Error>;
impl HasHeader for Header {
fn header(&self) -> Result<Header, crate::Error> {
Ok(self.clone())
/// View mapping emit functions. Used when implementing a view's `map()`
/// function.
pub trait Emit {
/// Creates a `Map` result with an empty key and value.
fn emit(&self) -> Result<Mappings<(), ()>, crate::Error> {
self.emit_key_and_value((), ())
/// Creates a `Map` result with an empty key and value if `condition` is
/// true.
fn emit_if(&self, condition: bool) -> Result<Mappings<(), ()>, crate::Error> {
if condition {
self.emit()
} else {
Ok(Mappings::default())
/// Creates a `Map` result with a `key` and an empty value.
fn emit_key<K>(&self, key: K) -> Result<Mappings<K, ()>, crate::Error> {
self.emit_key_and_value(key, ())
/// Creates a `Map` result with `value` and an empty key.
fn emit_value<Value>(&self, value: Value) -> Result<Mappings<(), Value>, crate::Error> {
self.emit_key_and_value((), value)
/// Creates a `Map` result with a `key` and `value`.
fn emit_key_and_value<K, Value>(
&self,
key: K,
value: Value,
) -> Result<Mappings<K, Value>, crate::Error>;
impl Emit for Header {
) -> Result<Mappings<K, Value>, crate::Error> {
Ok(Mappings::Simple(Some(Map::new(self.clone(), key, value))))
impl Display for Header {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.id.fmt(f)?;
f.write_char('@')?;
self.revision.fmt(f)
/// A header for a [`CollectionDocument`].
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash)]
pub struct CollectionHeader<PrimaryKey> {
/// The unique id of the document.
pub id: PrimaryKey,
/// The revision of the document.
impl<PrimaryKey> Emit for CollectionHeader<PrimaryKey>
where
PrimaryKey: for<'k> Key<'k>,
{
let header = Header::try_from(self.clone())?;
Ok(Mappings::Simple(Some(Map::new(header, key, value))))
impl<PrimaryKey> HasHeader for CollectionHeader<PrimaryKey>
Header::try_from(self.clone())
impl HasHeader for OwnedDocument {
self.header.header()
impl<'a> HasHeader for BorrowedDocument<'a> {
impl<C> HasHeader for CollectionDocument<C>
C: SerializedCollection,
impl<PrimaryKey> TryFrom<Header> for CollectionHeader<PrimaryKey>
type Error = crate::Error;
fn try_from(value: Header) -> Result<Self, Self::Error> {
Ok(Self {
id: value.id.deserialize::<PrimaryKey>()?,
revision: value.revision,
})
impl<'a, PrimaryKey> TryFrom<&'a Header> for CollectionHeader<PrimaryKey>
fn try_from(value: &'a Header) -> Result<Self, Self::Error> {
impl<PrimaryKey> TryFrom<CollectionHeader<PrimaryKey>> for Header
fn try_from(value: CollectionHeader<PrimaryKey>) -> Result<Self, Self::Error> {
id: DocumentId::new(&value.id)?,
impl<'a, PrimaryKey> TryFrom<&'a CollectionHeader<PrimaryKey>> for Header
fn try_from(value: &'a CollectionHeader<PrimaryKey>) -> Result<Self, Self::Error> {
/// A header with either a serialized or deserialized primary key.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum AnyHeader<PrimaryKey> {
/// A serialized header.
Serialized(Header),
/// A deserialized header.
Collection(CollectionHeader<PrimaryKey>),
impl<PrimaryKey> AnyHeader<PrimaryKey>
/// Returns the contained header as a [`Header`].
pub fn into_header(self) -> Result<Header, crate::Error> {
match self {
AnyHeader::Serialized(header) => Ok(header),
AnyHeader::Collection(header) => Header::try_from(header),
#[test]
fn emissions_tests() -> Result<(), crate::Error> {
use crate::schema::Map;
use crate::test_util::Basic;
let doc = BorrowedDocument::with_contents::<Basic, _>(&1, &Basic::default())?;
assert_eq!(
doc.header.emit()?,
Mappings::Simple(Some(Map::new(doc.header.clone(), (), ())))
);
doc.header.emit_key(1)?,
Mappings::Simple(Some(Map::new(doc.header.clone(), 1, ())))
doc.header.emit_value(1)?,
Mappings::Simple(Some(Map::new(doc.header.clone(), (), 1)))
doc.header.emit_key_and_value(1, 2)?,
Mappings::Simple(Some(Map::new(doc.header, 1, 2)))
Ok(())
fn chained_mappings_test() -> Result<(), crate::Error> {
doc.header.emit()?.and(doc.header.emit()?),
Mappings::List(vec![
Map::new(doc.header.clone(), (), ()),
Map::new(doc.header, (), ())
])
fn header_display_test() {
let original_contents = b"one";
let revision = Revision::new(original_contents);
let header = Header {
id: DocumentId::new(&42_u64).unwrap(),
revision,
};
header.to_string(),
"7$2a@0-7692c3ad3540bb803c020b3aee66cd8887123234ea0c6e7143c0add73ff431ed"