use std::borrow::Cow;
use arc_bytes::serde::{Bytes, CowBytes};
use serde::{Deserialize, Serialize};
use crate::key::KeyEncoding;
use crate::schema::{Collection, SerializedCollection};
mod collection;
mod header;
mod id;
mod revision;
pub use self::collection::{CollectionDocument, OwnedDocuments};
pub use self::header::{AnyHeader, CollectionHeader, Emit, HasHeader, Header};
pub use self::id::{DocumentId, InvalidHexadecimal};
pub use self::revision::Revision;
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BorrowedDocument<'a> {
pub header: Header,
#[serde(borrow)]
pub contents: CowBytes<'a>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct OwnedDocument {
pub header: Header,
pub contents: Bytes,
}
pub trait Document<C>: Sized
where
C: Collection,
{
type Bytes;
fn id(&self) -> &DocumentId;
fn header(&self) -> AnyHeader<C::PrimaryKey>;
fn set_header(&mut self, header: Header) -> Result<(), crate::Error>;
fn set_collection_header(
&mut self,
header: CollectionHeader<C::PrimaryKey>,
) -> Result<(), crate::Error> {
self.set_header(Header::try_from(header)?)
}
fn bytes(&self) -> Result<Vec<u8>, crate::Error>;
fn contents(&self) -> Result<C::Contents, crate::Error>
where
C: SerializedCollection;
fn set_contents(&mut self, contents: C::Contents) -> Result<(), crate::Error>
where
C: SerializedCollection;
}
impl<'a> AsRef<[u8]> for BorrowedDocument<'a> {
fn as_ref(&self) -> &[u8] {
&self.contents
}
}
impl<'a, C> Document<C> for BorrowedDocument<'a>
where
C: Collection,
{
type Bytes = CowBytes<'a>;
fn contents(&self) -> Result<C::Contents, crate::Error>
where
C: SerializedCollection,
{
<C as SerializedCollection>::deserialize(&self.contents)
}
fn set_contents(&mut self, contents: C::Contents) -> Result<(), crate::Error>
where
C: SerializedCollection,
{
self.contents = CowBytes::from(<C as SerializedCollection>::serialize(&contents)?);
Ok(())
}
fn header(&self) -> AnyHeader<C::PrimaryKey> {
AnyHeader::Serialized(self.header.clone())
}
fn set_header(&mut self, header: Header) -> Result<(), crate::Error> {
self.header = header;
Ok(())
}
fn bytes(&self) -> Result<Vec<u8>, crate::Error> {
Ok(self.contents.to_vec())
}
fn id(&self) -> &DocumentId {
&self.header.id
}
}
impl<C> Document<C> for OwnedDocument
where
C: Collection,
{
type Bytes = Vec<u8>;
fn contents(&self) -> Result<C::Contents, crate::Error>
where
C: SerializedCollection,
{
<C as SerializedCollection>::deserialize(&self.contents)
}
fn set_contents(&mut self, contents: C::Contents) -> Result<(), crate::Error>
where
C: SerializedCollection,
{
self.contents = Bytes::from(<C as SerializedCollection>::serialize(&contents)?);
Ok(())
}
fn id(&self) -> &DocumentId {
&self.header.id
}
fn header(&self) -> AnyHeader<C::PrimaryKey> {
AnyHeader::Serialized(self.header.clone())
}
fn set_header(&mut self, header: Header) -> Result<(), crate::Error> {
self.header = header;
Ok(())
}
fn bytes(&self) -> Result<Vec<u8>, crate::Error> {
Ok(self.contents.to_vec())
}
}
impl AsRef<Header> for OwnedDocument {
fn as_ref(&self) -> &Header {
&self.header
}
}
impl AsMut<Header> for OwnedDocument {
fn as_mut(&mut self) -> &mut Header {
&mut self.header
}
}
impl AsRef<[u8]> for OwnedDocument {
fn as_ref(&self) -> &[u8] {
&self.contents
}
}
impl<'a> BorrowedDocument<'a> {
pub fn new<Contents: Into<CowBytes<'a>>>(id: DocumentId, contents: Contents) -> Self {
let contents = contents.into();
let revision = Revision::new(&contents);
Self {
header: Header { id, revision },
contents,
}
}
pub fn with_contents<C, PrimaryKey>(
id: &PrimaryKey,
contents: &C::Contents,
) -> Result<Self, crate::Error>
where
C: SerializedCollection,
PrimaryKey: KeyEncoding<C::PrimaryKey> + ?Sized,
{
let contents = <C as SerializedCollection>::serialize(contents)?;
Ok(Self::new(DocumentId::new(id)?, contents))
}
#[must_use]
pub fn into_owned(self) -> OwnedDocument {
OwnedDocument {
header: self.header,
contents: Bytes::from(self.contents),
}
}
}
impl<'a> AsRef<Header> for BorrowedDocument<'a> {
fn as_ref(&self) -> &Header {
&self.header
}
}
impl<'a> AsMut<Header> for BorrowedDocument<'a> {
fn as_mut(&mut self) -> &mut Header {
&mut self.header
}
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
pub enum KeyId {
None,
Master,
Id(Cow<'static, str>),
}