use std::collections::btree_map::Iter;
use std::collections::BTreeMap;
use crate::operation::traits::AsOperation;
use crate::operation::{OperationFields, OperationId, OperationValue};
use crate::WithId;
#[derive(Clone, Debug, PartialEq)]
pub struct DocumentViewValue {
operation_id: OperationId,
value: OperationValue,
}
impl DocumentViewValue {
pub fn new(operation_id: &OperationId, value: &OperationValue) -> Self {
Self {
operation_id: operation_id.clone(),
value: value.clone(),
}
}
pub fn id(&self) -> &OperationId {
&self.operation_id
}
pub fn value(&self) -> &OperationValue {
&self.value
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct DocumentViewFields(BTreeMap<String, DocumentViewValue>);
impl DocumentViewFields {
pub fn new() -> Self {
Self(BTreeMap::new())
}
pub fn new_from_operation_fields(id: &OperationId, fields: &OperationFields) -> Self {
let mut document_view_fields = DocumentViewFields::new();
for (name, value) in fields.iter() {
document_view_fields.insert(name, DocumentViewValue::new(id, value));
}
document_view_fields
}
pub fn insert(&mut self, name: &str, value: DocumentViewValue) -> Option<DocumentViewValue> {
self.0.insert(name.to_owned(), value)
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn get(&self, name: &str) -> Option<&DocumentViewValue> {
if !self.0.contains_key(name) {
return None;
}
self.0.get(name)
}
pub fn keys(&self) -> Vec<String> {
self.0.keys().cloned().collect()
}
pub fn iter(&self) -> Iter<String, DocumentViewValue> {
self.0.iter()
}
}
impl Default for DocumentViewFields {
fn default() -> Self {
Self::new()
}
}
impl<T: AsOperation + WithId<OperationId>> From<T> for DocumentViewFields {
fn from(operation: T) -> Self {
let mut document_view_fields = DocumentViewFields::new();
if let Some(fields) = operation.fields() {
for (name, value) in fields.iter() {
document_view_fields.insert(name, DocumentViewValue::new(operation.id(), value));
}
}
document_view_fields
}
}
#[cfg(test)]
mod tests {
use rstest::rstest;
use crate::document::{DocumentViewFields, DocumentViewValue};
use crate::operation::traits::AsOperation;
use crate::operation::{OperationId, OperationValue};
use crate::test_utils::fixtures::{published_operation, random_operation_id};
use crate::test_utils::memory_store::PublishedOperation;
use crate::WithId;
#[rstest]
fn construct_fields(#[from(random_operation_id)] value_id: OperationId) {
let mut fields = DocumentViewFields::new();
fields.insert(
"name",
DocumentViewValue::new(&value_id, &OperationValue::String("ʕ •ᴥ•ʔ Cafe!".into())),
);
fields.insert(
"owner",
DocumentViewValue::new(&value_id, &OperationValue::String("しろくま".into())),
);
fields.insert(
"house-number",
DocumentViewValue::new(&value_id, &OperationValue::Integer(12)),
);
assert_eq!(fields.len(), 3);
assert!(!fields.is_empty());
assert_eq!(
fields.get("name").unwrap(),
&DocumentViewValue::new(&value_id, &OperationValue::String("ʕ •ᴥ•ʔ Cafe!".into()))
);
assert_eq!(
fields.get("owner").unwrap(),
&DocumentViewValue::new(&value_id, &OperationValue::String("しろくま".into()))
);
assert_eq!(
fields.get("house-number").unwrap(),
&DocumentViewValue::new(&value_id, &OperationValue::Integer(12))
);
}
#[rstest]
fn from_published_operation(#[from(published_operation)] operation: PublishedOperation) {
let document_view_fields = DocumentViewFields::from(operation.clone());
let operation_fields = operation.fields().unwrap();
assert_eq!(document_view_fields.len(), operation_fields.len());
}
#[rstest]
fn new_from_operation_fields(#[from(published_operation)] operation: PublishedOperation) {
let document_view_fields = DocumentViewFields::new_from_operation_fields(
operation.id(),
&operation.fields().unwrap(),
);
let operation_fields = operation.fields().unwrap();
assert_eq!(document_view_fields.len(), operation_fields.len());
}
}