2026-02-13 12:00:39 -05:00
|
|
|
use crate::{
|
2026-02-13 12:13:47 -05:00
|
|
|
action::Field,
|
2026-02-13 15:04:16 -05:00
|
|
|
message::MessageAction,
|
2026-02-13 12:13:47 -05:00
|
|
|
mtterror::{ErrorID, MTTError},
|
|
|
|
|
name::{Name, NameType, Names},
|
2026-02-13 12:00:39 -05:00
|
|
|
};
|
2026-02-13 12:24:46 -05:00
|
|
|
use std::collections::HashMap;
|
2026-02-13 12:37:47 -05:00
|
|
|
use uuid::Uuid;
|
|
|
|
|
|
2026-02-13 12:48:17 -05:00
|
|
|
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
|
|
|
|
pub struct Oid {
|
|
|
|
|
oid: Uuid,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Oid {
|
|
|
|
|
pub fn new() -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
oid: Uuid::new_v4(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod oids {
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn are_oids_random() {
|
|
|
|
|
let count = 10;
|
|
|
|
|
let mut holder: Vec<Oid> = Vec::new();
|
|
|
|
|
while holder.len() < count {
|
|
|
|
|
let result = Oid::new();
|
|
|
|
|
assert!(!holder.contains(&result));
|
|
|
|
|
holder.push(result);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-13 12:37:47 -05:00
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
|
pub struct InternalRecord {
|
|
|
|
|
data: HashMap<Uuid, Field>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl InternalRecord {
|
|
|
|
|
pub fn new() -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
data: HashMap::new(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn insert<F>(&mut self, id: Uuid, data: F) -> Field
|
|
|
|
|
where
|
|
|
|
|
F: Into<Field>,
|
|
|
|
|
{
|
|
|
|
|
match self.data.insert(id, data.into()) {
|
|
|
|
|
Some(data) => data.clone(),
|
|
|
|
|
None => Field::None,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get(&self, id: &Uuid) -> Option<&Field> {
|
|
|
|
|
self.data.get(id)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn is_empty(&self) -> bool {
|
|
|
|
|
self.data.is_empty()
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-02-13 12:24:46 -05:00
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
|
pub struct InternalRecords {
|
|
|
|
|
data: HashMap<Oid, InternalRecord>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl InternalRecords {
|
|
|
|
|
pub fn new() -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
data: HashMap::new(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn insert(&mut self, oid: Oid, record: InternalRecord) -> Option<InternalRecord> {
|
|
|
|
|
self.data.insert(oid, record)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get(&self, oid: &Oid) -> Option<&InternalRecord> {
|
|
|
|
|
self.data.get(oid)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn remove(&mut self, oid: &Oid) -> Option<InternalRecord> {
|
|
|
|
|
self.data.remove(oid)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn iter(&self) -> impl Iterator<Item = (&Oid, &InternalRecord)> {
|
|
|
|
|
self.data.iter()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn keys(&self) -> impl Iterator<Item = &Oid> {
|
|
|
|
|
self.data.keys()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn values(&self) -> impl Iterator<Item = &InternalRecord> {
|
|
|
|
|
self.data.values()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn contains_key(&self, oid: &Oid) -> bool {
|
|
|
|
|
self.data.contains_key(oid)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn len(&self) -> usize {
|
|
|
|
|
self.data.len()
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-02-13 12:00:39 -05:00
|
|
|
|
2026-02-13 12:13:47 -05:00
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
|
pub struct Record {
|
|
|
|
|
names: Names,
|
|
|
|
|
data: InternalRecord,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Record {
|
|
|
|
|
pub fn with_data(names: Names, rec: InternalRecord) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
names: names,
|
|
|
|
|
data: rec,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get<NT>(&self, field_id: NT) -> Result<Field, MTTError>
|
|
|
|
|
where
|
|
|
|
|
NT: Into<NameType>,
|
|
|
|
|
{
|
|
|
|
|
let id = match self.names.get_id(field_id) {
|
|
|
|
|
Ok(data) => data,
|
|
|
|
|
Err(err) => return Err(err),
|
|
|
|
|
};
|
|
|
|
|
match self.data.get(&id) {
|
|
|
|
|
Some(data) => Ok(data.clone()),
|
|
|
|
|
None => Err(MTTError::new(NameType::None, ErrorID::FieldMissingData)),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-13 12:00:39 -05:00
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
|
pub struct Records {
|
2026-02-13 15:04:16 -05:00
|
|
|
doc_name: NameType,
|
2026-02-13 12:00:39 -05:00
|
|
|
names: Names,
|
|
|
|
|
data: InternalRecords,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Records {
|
2026-02-13 15:04:16 -05:00
|
|
|
pub fn new(doc_names: Vec<Name>, names: Names) -> Self {
|
2026-02-13 12:00:39 -05:00
|
|
|
Self {
|
2026-02-13 15:04:16 -05:00
|
|
|
doc_name: doc_names[0].clone().into(),
|
2026-02-13 12:00:39 -05:00
|
|
|
names: names,
|
|
|
|
|
data: InternalRecords::new(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-13 15:04:16 -05:00
|
|
|
pub fn with_data(doc_names: Vec<Name>, names: Names, records: InternalRecords) -> Self {
|
2026-02-13 12:00:39 -05:00
|
|
|
Self {
|
2026-02-13 15:04:16 -05:00
|
|
|
doc_name: doc_names[0].clone().into(),
|
2026-02-13 12:00:39 -05:00
|
|
|
names: names,
|
|
|
|
|
data: records,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn insert(&mut self, oid: Oid, record: InternalRecord) -> Option<InternalRecord> {
|
|
|
|
|
self.data.insert(oid, record)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn len(&self) -> usize {
|
|
|
|
|
self.data.len()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn iter(&self) -> impl Iterator<Item = Record> {
|
|
|
|
|
RecordIter::new(self)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_internal_records(&self) -> &InternalRecords {
|
|
|
|
|
&self.data
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-13 15:04:16 -05:00
|
|
|
impl MessageAction for Records {
|
|
|
|
|
fn doc_name(&self) -> &NameType {
|
|
|
|
|
&self.doc_name
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-13 12:00:39 -05:00
|
|
|
struct RecordIter {
|
|
|
|
|
names: Names,
|
|
|
|
|
recs: Vec<InternalRecord>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl RecordIter {
|
|
|
|
|
fn new(records: &Records) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
names: records.names.clone(),
|
|
|
|
|
recs: records.data.values().cloned().collect(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Iterator for RecordIter {
|
|
|
|
|
type Item = Record;
|
|
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
|
|
match self.recs.pop() {
|
|
|
|
|
Some(rec) => Some(Record::with_data(self.names.clone(), rec.clone())),
|
|
|
|
|
None => None,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-02-13 15:04:16 -05:00
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod records {
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn does_recourds_store_document_name() {
|
|
|
|
|
let doc_name = Name::english(uuid::Uuid::new_v4().to_string().as_str());
|
|
|
|
|
let expected: NameType = doc_name.clone().into();
|
|
|
|
|
let recs = Records::new(vec![doc_name.clone()], Names::new());
|
|
|
|
|
assert_eq!(recs.doc_name(), &expected);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn does_records_with_data_store_document_name() {
|
|
|
|
|
let doc_name = Name::english(uuid::Uuid::new_v4().to_string().as_str());
|
|
|
|
|
let expected: NameType = doc_name.clone().into();
|
|
|
|
|
let recs = Records::with_data(vec![doc_name.clone()], Names::new(), InternalRecords::new());
|
|
|
|
|
assert_eq!(recs.doc_name(), &expected);
|
|
|
|
|
}
|
|
|
|
|
}
|