use serde::{Deserialize, Serialize};
use crate::document::{DocumentId, DocumentViewId, DocumentViewIdError};
use crate::hash::HashError;
use crate::Validate;
use super::OperationId;
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct Relation(DocumentId);
impl Relation {
pub fn new(document: DocumentId) -> Self {
Self(document)
}
pub fn document_id(&self) -> &DocumentId {
&self.0
}
}
impl Validate for Relation {
type Error = HashError;
fn validate(&self) -> Result<(), Self::Error> {
self.0.validate()
}
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct PinnedRelation(DocumentViewId);
impl PinnedRelation {
pub fn new(document_view_id: DocumentViewId) -> Self {
Self(document_view_id)
}
pub fn view_id(&self) -> &DocumentViewId {
&self.0
}
}
impl Validate for PinnedRelation {
type Error = DocumentViewIdError;
fn validate(&self) -> Result<(), Self::Error> {
self.0.validate()
}
}
impl IntoIterator for PinnedRelation {
type Item = OperationId;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct RelationList(Vec<DocumentId>);
impl RelationList {
pub fn new(relations: Vec<DocumentId>) -> Self {
Self(relations)
}
pub fn iter(&self) -> std::vec::IntoIter<DocumentId> {
self.0.clone().into_iter()
}
}
impl Validate for RelationList {
type Error = HashError;
fn validate(&self) -> Result<(), Self::Error> {
for document_id in &self.0 {
document_id.validate()?;
}
Ok(())
}
}
impl IntoIterator for RelationList {
type Item = DocumentId;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct PinnedRelationList(Vec<DocumentViewId>);
impl PinnedRelationList {
pub fn new(relations: Vec<DocumentViewId>) -> Self {
Self(relations)
}
pub fn iter(&self) -> std::vec::IntoIter<DocumentViewId> {
self.0.clone().into_iter()
}
}
impl Validate for PinnedRelationList {
type Error = DocumentViewIdError;
fn validate(&self) -> Result<(), Self::Error> {
for document_view in &self.0 {
document_view.validate()?;
}
Ok(())
}
}
impl IntoIterator for PinnedRelationList {
type Item = DocumentViewId;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
#[cfg(test)]
mod tests {
use rstest::rstest;
use crate::document::{DocumentId, DocumentViewId};
use crate::hash::Hash;
use crate::test_utils::fixtures::{random_document_id, random_hash};
use crate::Validate;
use super::{PinnedRelation, PinnedRelationList, Relation, RelationList};
#[rstest]
fn validation(
#[from(random_document_id)] document_1: DocumentId,
#[from(random_document_id)] document_2: DocumentId,
#[from(random_hash)] operation_id_1: Hash,
#[from(random_hash)] operation_id_2: Hash,
) {
let relation = Relation::new(document_1.clone());
assert!(relation.validate().is_ok());
let pinned_relation = PinnedRelation::new(DocumentViewId::from(operation_id_1.clone()));
assert!(pinned_relation.validate().is_ok());
let relation_list = RelationList::new(vec![document_1, document_2]);
assert!(relation_list.validate().is_ok());
let pinned_relation_list =
PinnedRelationList::new(vec![operation_id_1.into(), operation_id_2.into()]);
assert!(pinned_relation_list.validate().is_ok());
}
#[rstest]
fn iterates(#[from(random_hash)] hash_1: Hash, #[from(random_hash)] hash_2: Hash) {
let pinned_relation = PinnedRelation::new(
DocumentViewId::new(&[hash_1.clone().into(), hash_2.clone().into()]).unwrap(),
);
for hash in pinned_relation {
assert!(hash.validate().is_ok());
}
let relation_list = RelationList::new(vec![
DocumentId::new(hash_1.clone().into()),
DocumentId::new(hash_2.clone().into()),
]);
for document_id in relation_list {
assert!(document_id.validate().is_ok());
}
let pinned_relation_list = PinnedRelationList::new(vec![
DocumentViewId::from(hash_1),
DocumentViewId::from(hash_2),
]);
for pinned_relation in pinned_relation_list {
for hash in pinned_relation {
assert!(hash.validate().is_ok());
}
}
}
#[rstest]
fn list_equality(
#[from(random_document_id)] document_1: DocumentId,
#[from(random_document_id)] document_2: DocumentId,
#[from(random_hash)] operation_id_1: Hash,
#[from(random_hash)] operation_id_2: Hash,
) {
let relation_list = RelationList::new(vec![document_1.clone(), document_2.clone()]);
let relation_list_different_order = RelationList::new(vec![document_2, document_1]);
assert_ne!(relation_list, relation_list_different_order);
let pinned_relation_list = PinnedRelationList::new(vec![
operation_id_1.clone().into(),
operation_id_2.clone().into(),
]);
let pinned_relation_list_different_order =
PinnedRelationList::new(vec![operation_id_2.into(), operation_id_1.into()]);
assert_ne!(pinned_relation_list, pinned_relation_list_different_order);
}
}