Added a record iterator.
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 1s
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 1s
This commit is contained in:
parent
7755947816
commit
5fb6035069
392
src/message.rs
392
src/message.rs
@ -1,7 +1,7 @@
|
|||||||
use chrono::prelude::*;
|
use chrono::prelude::*;
|
||||||
use isolang::Language;
|
use isolang::Language;
|
||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet, VecDeque},
|
||||||
sync::{
|
sync::{
|
||||||
mpsc::{channel, Receiver, Sender},
|
mpsc::{channel, Receiver, Sender},
|
||||||
Arc, RwLock,
|
Arc, RwLock,
|
||||||
@ -28,6 +28,7 @@ enum MTTError {
|
|||||||
DocumentNotFound(String),
|
DocumentNotFound(String),
|
||||||
FieldDuplicate(String, Field),
|
FieldDuplicate(String, Field),
|
||||||
FieldMissingData,
|
FieldMissingData,
|
||||||
|
RecordMismatch,
|
||||||
NameDuplicate(Name),
|
NameDuplicate(Name),
|
||||||
NameInvalidID(Uuid),
|
NameInvalidID(Uuid),
|
||||||
NameMissingTranslation(Language),
|
NameMissingTranslation(Language),
|
||||||
@ -267,7 +268,11 @@ impl Message {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_path(&self) -> Path {
|
fn get_path(&self) -> Path {
|
||||||
Path::new(Include::Some(self.msg_id.clone()), Include::Some(self.document_id.clone()), Include::Some(self.action.clone().into()))
|
Path::new(
|
||||||
|
Include::Some(self.msg_id.clone()),
|
||||||
|
Include::Some(self.document_id.clone()),
|
||||||
|
Include::Some(self.action.clone().into()),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn response<A>(&self, action: A) -> Self
|
fn response<A>(&self, action: A) -> Self
|
||||||
@ -288,9 +293,15 @@ mod messages {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn can_the_document_be_a_stringi_reference() {
|
fn can_the_document_be_a_stringi_reference() {
|
||||||
let dts = [Name::english("one".to_string()), Name::english("two".to_string())];
|
let dts = [
|
||||||
|
Name::english("one".to_string()),
|
||||||
|
Name::english("two".to_string()),
|
||||||
|
];
|
||||||
for document in dts.into_iter() {
|
for document in dts.into_iter() {
|
||||||
let msg = Message::new(document.clone(), MsgAction::Create(DocDef::new(document.clone())));
|
let msg = Message::new(
|
||||||
|
document.clone(),
|
||||||
|
MsgAction::Create(DocDef::new(document.clone())),
|
||||||
|
);
|
||||||
match msg.get_document_id() {
|
match msg.get_document_id() {
|
||||||
NameType::Name(data) => assert_eq!(data, &document),
|
NameType::Name(data) => assert_eq!(data, &document),
|
||||||
_ => unreachable!("should have been a string id"),
|
_ => unreachable!("should have been a string id"),
|
||||||
@ -551,7 +562,7 @@ impl ToString for Name {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
struct Names {
|
struct Names {
|
||||||
names: HashMap<Name, Uuid>,
|
names: HashMap<Name, Uuid>,
|
||||||
ids: HashMap<Uuid, HashMap<Language, Name>>,
|
ids: HashMap<Uuid, HashMap<Language, Name>>,
|
||||||
@ -605,18 +616,23 @@ impl Names {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_id<NT>(&self, name: NT) -> Result<Uuid, MTTError> where NT: Into<NameType> {
|
fn get_id<NT>(&self, name: NT) -> Result<Uuid, MTTError>
|
||||||
|
where
|
||||||
|
NT: Into<NameType>,
|
||||||
|
{
|
||||||
match name.into() {
|
match name.into() {
|
||||||
NameType::Name(data) => match self.names.get(&data) {
|
NameType::Name(data) => match self.names.get(&data) {
|
||||||
Some(id) => Ok(id.clone()),
|
Some(id) => Ok(id.clone()),
|
||||||
None => Err(MTTError::NameNotFound(data.clone())),
|
None => Err(MTTError::NameNotFound(data.clone())),
|
||||||
}
|
},
|
||||||
NameType::ID(data) => if self.ids.contains_key(&data) {
|
NameType::ID(data) => {
|
||||||
|
if self.ids.contains_key(&data) {
|
||||||
Ok(data)
|
Ok(data)
|
||||||
} else {
|
} else {
|
||||||
Err(MTTError::NameNotFound(Name::english(data.to_string())))
|
Err(MTTError::NameNotFound(Name::english(data.to_string())))
|
||||||
}
|
}
|
||||||
NameType::None => Err(MTTError::NameNotFound(Name::english("none".to_string())))
|
}
|
||||||
|
NameType::None => Err(MTTError::NameNotFound(Name::english("none".to_string()))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -643,6 +659,10 @@ impl Names {
|
|||||||
};
|
};
|
||||||
Ok(Route::new(path.msg_id.clone(), doc_id, path.action.clone()))
|
Ok(Route::new(path.msg_id.clone(), doc_id, path.action.clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_empty(&self) -> bool {
|
||||||
|
self.names.is_empty()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -1400,7 +1420,6 @@ mod queuedatas {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
struct DocRegistry {
|
struct DocRegistry {
|
||||||
doc_names: Names,
|
doc_names: Names,
|
||||||
queue: Queue,
|
queue: Queue,
|
||||||
@ -1447,8 +1466,11 @@ impl DocRegistry {
|
|||||||
for send_id in send_to.iter() {
|
for send_id in send_to.iter() {
|
||||||
self.queue.forward(send_id, msg.clone());
|
self.queue.forward(send_id, msg.clone());
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
Err(err) => self.queue.send(msg.response(MsgAction::Error(err))).unwrap(),
|
Err(err) => self
|
||||||
|
.queue
|
||||||
|
.send(msg.response(MsgAction::Error(err)))
|
||||||
|
.unwrap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1459,8 +1481,8 @@ impl DocRegistry {
|
|||||||
match reg.get_msg() {
|
match reg.get_msg() {
|
||||||
RegMsg::AddDocName(name) => match self.doc_names.add_name(name.clone()) {
|
RegMsg::AddDocName(name) => match self.doc_names.add_name(name.clone()) {
|
||||||
Ok(_) => reg.response(RegMsg::Ok),
|
Ok(_) => reg.response(RegMsg::Ok),
|
||||||
Err(err) => reg.response(RegMsg::Error(err))
|
Err(err) => reg.response(RegMsg::Error(err)),
|
||||||
}
|
},
|
||||||
RegMsg::AddRoute(path) => {
|
RegMsg::AddRoute(path) => {
|
||||||
let route = self.doc_names.path_to_route(path).unwrap();
|
let route = self.doc_names.path_to_route(path).unwrap();
|
||||||
let route_id: RouteID = route.into();
|
let route_id: RouteID = route.into();
|
||||||
@ -1722,7 +1744,10 @@ mod queues {
|
|||||||
fn can_register_routes() {
|
fn can_register_routes() {
|
||||||
let mut tester = TestQueue::new();
|
let mut tester = TestQueue::new();
|
||||||
let mut queue = tester.get_queue();
|
let mut queue = tester.get_queue();
|
||||||
let names = [Name::english("task".to_string()), Name::english("recipe".to_string())];
|
let names = [
|
||||||
|
Name::english("task".to_string()),
|
||||||
|
Name::english("recipe".to_string()),
|
||||||
|
];
|
||||||
for name in names.iter() {
|
for name in names.iter() {
|
||||||
tester.add_document(name.clone());
|
tester.add_document(name.clone());
|
||||||
}
|
}
|
||||||
@ -1749,7 +1774,10 @@ mod queues {
|
|||||||
fn can_multiple_register_for_the_same_route() {
|
fn can_multiple_register_for_the_same_route() {
|
||||||
let mut tester = TestQueue::new();
|
let mut tester = TestQueue::new();
|
||||||
let mut queue = tester.get_queue();
|
let mut queue = tester.get_queue();
|
||||||
let names = [Name::english("task".to_string()), Name::english("recipe".to_string())];
|
let names = [
|
||||||
|
Name::english("task".to_string()),
|
||||||
|
Name::english("recipe".to_string()),
|
||||||
|
];
|
||||||
let route_req = Path::new(Include::All, Include::All, Include::All);
|
let route_req = Path::new(Include::All, Include::All, Include::All);
|
||||||
let reg_msg = RegMsg::AddRoute(route_req);
|
let reg_msg = RegMsg::AddRoute(route_req);
|
||||||
for name in names.iter() {
|
for name in names.iter() {
|
||||||
@ -1775,7 +1803,11 @@ mod queues {
|
|||||||
tester.add_document(name.clone());
|
tester.add_document(name.clone());
|
||||||
let paths = [
|
let paths = [
|
||||||
Path::new(Include::All, Include::All, Include::All),
|
Path::new(Include::All, Include::All, Include::All),
|
||||||
Path::new(Include::All, Include::Some(name.clone().into()), Include::All),
|
Path::new(
|
||||||
|
Include::All,
|
||||||
|
Include::Some(name.clone().into()),
|
||||||
|
Include::All,
|
||||||
|
),
|
||||||
];
|
];
|
||||||
for path in paths.iter() {
|
for path in paths.iter() {
|
||||||
let reg_msg = RegMsg::AddRoute(path.clone());
|
let reg_msg = RegMsg::AddRoute(path.clone());
|
||||||
@ -1801,12 +1833,19 @@ mod queues {
|
|||||||
fn can_routing_be_based_on_message_id() {
|
fn can_routing_be_based_on_message_id() {
|
||||||
let mut tester = TestQueue::new();
|
let mut tester = TestQueue::new();
|
||||||
let mut queue = tester.get_queue();
|
let mut queue = tester.get_queue();
|
||||||
let names = [Name::english("one".to_string()), Name::english("two".to_string())];
|
let names = [
|
||||||
|
Name::english("one".to_string()),
|
||||||
|
Name::english("two".to_string()),
|
||||||
|
];
|
||||||
let mut inputs: HashMap<Name, Message> = HashMap::new();
|
let mut inputs: HashMap<Name, Message> = HashMap::new();
|
||||||
for name in names.iter() {
|
for name in names.iter() {
|
||||||
tester.add_document(name.clone());
|
tester.add_document(name.clone());
|
||||||
let input = Message::new(name.clone(), Query::new());
|
let input = Message::new(name.clone(), Query::new());
|
||||||
let path = Path::new(Include::Some(input.get_message_id().clone()), Include::All, Include::All);
|
let path = Path::new(
|
||||||
|
Include::Some(input.get_message_id().clone()),
|
||||||
|
Include::All,
|
||||||
|
Include::All,
|
||||||
|
);
|
||||||
let reg_msg = RegMsg::AddRoute(path);
|
let reg_msg = RegMsg::AddRoute(path);
|
||||||
let reg = Register::new(tester.get_doc_rx_id(&name).clone(), reg_msg);
|
let reg = Register::new(tester.get_doc_rx_id(&name).clone(), reg_msg);
|
||||||
let msg = Message::new(NameType::None, reg);
|
let msg = Message::new(NameType::None, reg);
|
||||||
@ -1835,12 +1874,19 @@ mod queues {
|
|||||||
fn can_routing_be_based_on_document_name() {
|
fn can_routing_be_based_on_document_name() {
|
||||||
let mut tester = TestQueue::new();
|
let mut tester = TestQueue::new();
|
||||||
let mut queue = tester.get_queue();
|
let mut queue = tester.get_queue();
|
||||||
let names = [Name::english("one".to_string()), Name::english("two".to_string())];
|
let names = [
|
||||||
|
Name::english("one".to_string()),
|
||||||
|
Name::english("two".to_string()),
|
||||||
|
];
|
||||||
let mut inputs: HashMap<Name, Message> = HashMap::new();
|
let mut inputs: HashMap<Name, Message> = HashMap::new();
|
||||||
for name in names.iter() {
|
for name in names.iter() {
|
||||||
tester.add_document(name.clone());
|
tester.add_document(name.clone());
|
||||||
let input = Message::new(name.clone(), Query::new());
|
let input = Message::new(name.clone(), Query::new());
|
||||||
let path = Path::new(Include::All, Include::Some(name.clone().into()), Include::All);
|
let path = Path::new(
|
||||||
|
Include::All,
|
||||||
|
Include::Some(name.clone().into()),
|
||||||
|
Include::All,
|
||||||
|
);
|
||||||
let reg_msg = RegMsg::AddRoute(path);
|
let reg_msg = RegMsg::AddRoute(path);
|
||||||
let reg = Register::new(tester.get_doc_rx_id(&name).clone(), reg_msg);
|
let reg = Register::new(tester.get_doc_rx_id(&name).clone(), reg_msg);
|
||||||
let msg = Message::new(NameType::None, reg);
|
let msg = Message::new(NameType::None, reg);
|
||||||
@ -1869,7 +1915,10 @@ mod queues {
|
|||||||
fn can_routing_be_based_on_action() {
|
fn can_routing_be_based_on_action() {
|
||||||
let mut tester = TestQueue::new();
|
let mut tester = TestQueue::new();
|
||||||
let mut queue = tester.get_queue();
|
let mut queue = tester.get_queue();
|
||||||
let names = [Name::english("one".to_string()), Name::english("two".to_string())];
|
let names = [
|
||||||
|
Name::english("one".to_string()),
|
||||||
|
Name::english("two".to_string()),
|
||||||
|
];
|
||||||
let paths = [
|
let paths = [
|
||||||
Path::new(Include::All, Include::All, Include::Some(Action::Reply)),
|
Path::new(Include::All, Include::All, Include::Some(Action::Reply)),
|
||||||
Path::new(Include::All, Include::All, Include::Some(Action::Error)),
|
Path::new(Include::All, Include::All, Include::Some(Action::Error)),
|
||||||
@ -2080,6 +2129,20 @@ impl From<i128> for Field {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<isize> for Field {
|
||||||
|
fn from(value: isize) -> Self {
|
||||||
|
let data: i128 = value.try_into().unwrap();
|
||||||
|
Self::from(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<i32> for Field {
|
||||||
|
fn from(value: i32) -> Self {
|
||||||
|
let data: i128 = value.into();
|
||||||
|
Self::from(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod fields {
|
mod fields {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -2291,7 +2354,10 @@ impl Addition {
|
|||||||
self.data.add_field(name, field);
|
self.data.add_field(name, field);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_field<NT>(&self, name: NT) -> Option<Field> where NT: Into<NameType> {
|
fn get_field<NT>(&self, name: NT) -> Option<Field>
|
||||||
|
where
|
||||||
|
NT: Into<NameType>,
|
||||||
|
{
|
||||||
self.data.get_field(name)
|
self.data.get_field(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2392,14 +2458,20 @@ impl DocDef {
|
|||||||
self.fields.insert(id, FieldSetting::new(ftype));
|
self.fields.insert(id, FieldSetting::new(ftype));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_field_id<NT>(&self, field_name: NT) -> Result<Uuid, MTTError> where NT: Into<NameType> {
|
fn get_field_id<NT>(&self, field_name: NT) -> Result<Uuid, MTTError>
|
||||||
|
where
|
||||||
|
NT: Into<NameType>,
|
||||||
|
{
|
||||||
match self.field_names.get_id(field_name) {
|
match self.field_names.get_id(field_name) {
|
||||||
Ok(data) => Ok(data),
|
Ok(data) => Ok(data),
|
||||||
Err(err) => Err(err),
|
Err(err) => Err(err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_field<NT>(&self, field_name: NT) -> Result<&FieldSetting, MTTError> where NT: Into<NameType> {
|
fn get_field<NT>(&self, field_name: NT) -> Result<&FieldSetting, MTTError>
|
||||||
|
where
|
||||||
|
NT: Into<NameType>,
|
||||||
|
{
|
||||||
let id = match self.field_names.get_id(field_name) {
|
let id = match self.field_names.get_id(field_name) {
|
||||||
Ok(data) => data,
|
Ok(data) => data,
|
||||||
Err(err) => return Err(err),
|
Err(err) => return Err(err),
|
||||||
@ -2407,7 +2479,10 @@ impl DocDef {
|
|||||||
Ok(self.fields.get(&id).unwrap())
|
Ok(self.fields.get(&id).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_field_mut<NT>(&mut self, field_name: NT) -> Result<&mut FieldSetting, MTTError> where NT: Into<NameType> {
|
fn get_field_mut<NT>(&mut self, field_name: NT) -> Result<&mut FieldSetting, MTTError>
|
||||||
|
where
|
||||||
|
NT: Into<NameType>,
|
||||||
|
{
|
||||||
let id = match self.field_names.get_id(field_name) {
|
let id = match self.field_names.get_id(field_name) {
|
||||||
Ok(data) => data,
|
Ok(data) => data,
|
||||||
Err(err) => return Err(err),
|
Err(err) => return Err(err),
|
||||||
@ -2419,7 +2494,10 @@ impl DocDef {
|
|||||||
self.fields.keys().cloned().collect()
|
self.fields.keys().cloned().collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate<NT>(&self, field_name: NT, value: Option<Field>) -> Result<Field, MTTError> where NT: Into<NameType> {
|
fn validate<NT>(&self, field_name: NT, value: Option<Field>) -> Result<Field, MTTError>
|
||||||
|
where
|
||||||
|
NT: Into<NameType>,
|
||||||
|
{
|
||||||
let id = match self.field_names.get_id(field_name) {
|
let id = match self.field_names.get_id(field_name) {
|
||||||
Ok(data) => data,
|
Ok(data) => data,
|
||||||
Err(err) => return Err(err),
|
Err(err) => return Err(err),
|
||||||
@ -2437,7 +2515,6 @@ impl DocDef {
|
|||||||
Err(err) => Err(err),
|
Err(err) => Err(err),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
let setting = match self.get_field_mut(field_name) {
|
let setting = match self.get_field_mut(field_name) {
|
||||||
Ok(data) => data,
|
Ok(data) => data,
|
||||||
@ -2458,9 +2535,6 @@ impl DocDef {
|
|||||||
self.indexes.insert(id.clone(), index_type);
|
self.indexes.insert(id.clone(), index_type);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
let setting = match self.get_field(&field_name) {
|
let setting = match self.get_field(&field_name) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
@ -3122,7 +3196,10 @@ impl Query {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add<NT>(&mut self, name: NT, operation: Calculation) -> Result<(), MTTError> where NT: Into<NameType> {
|
fn add<NT>(&mut self, name: NT, operation: Calculation) -> Result<(), MTTError>
|
||||||
|
where
|
||||||
|
NT: Into<NameType>,
|
||||||
|
{
|
||||||
match operation.operation() {
|
match operation.operation() {
|
||||||
Operand::Equal => {
|
Operand::Equal => {
|
||||||
self.data.insert(name.into(), operation);
|
self.data.insert(name.into(), operation);
|
||||||
@ -3132,7 +3209,10 @@ impl Query {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get<NT>(&self, name: NT) -> Option<Calculation> where NT: Into<NameType> {
|
fn get<NT>(&self, name: NT) -> Option<Calculation>
|
||||||
|
where
|
||||||
|
NT: Into<NameType>,
|
||||||
|
{
|
||||||
match self.data.get(&name.into()) {
|
match self.data.get(&name.into()) {
|
||||||
Some(calc) => Some(calc.clone()),
|
Some(calc) => Some(calc.clone()),
|
||||||
None => None,
|
None => None,
|
||||||
@ -3298,7 +3378,7 @@ mod replies {
|
|||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
struct Record {
|
struct Record {
|
||||||
names: Names,
|
names: Names,
|
||||||
data: HashMap<Uuid, Field>
|
data: HashMap<Uuid, Field>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Record {
|
impl Record {
|
||||||
@ -3309,7 +3389,11 @@ impl Record {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert<NT, F>(&mut self, field_id: NT, data: F) -> Result<(), MTTError> where F: Into<Field>, NT: Into<NameType> {
|
fn insert<NT, F>(&mut self, field_id: NT, data: F) -> Result<(), MTTError>
|
||||||
|
where
|
||||||
|
F: Into<Field>,
|
||||||
|
NT: Into<NameType>,
|
||||||
|
{
|
||||||
let id = match self.names.get_id(field_id) {
|
let id = match self.names.get_id(field_id) {
|
||||||
Ok(data) => data,
|
Ok(data) => data,
|
||||||
Err(err) => return Err(err),
|
Err(err) => return Err(err),
|
||||||
@ -3318,7 +3402,10 @@ impl Record {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get<NT>(&self, field_id: NT) -> Result<Field, MTTError> where NT: Into<NameType> {
|
fn get<NT>(&self, field_id: NT) -> Result<Field, MTTError>
|
||||||
|
where
|
||||||
|
NT: Into<NameType>,
|
||||||
|
{
|
||||||
let id = match self.names.get_id(field_id) {
|
let id = match self.names.get_id(field_id) {
|
||||||
Ok(data) => data,
|
Ok(data) => data,
|
||||||
Err(err) => return Err(err),
|
Err(err) => return Err(err),
|
||||||
@ -3331,66 +3418,59 @@ impl Record {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
struct Records {
|
struct RecordIter {
|
||||||
names: Names,
|
names: Names,
|
||||||
records: Vec<Record>,
|
records: VecDeque<HashMap<Uuid, Field>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Records {
|
impl RecordIter {
|
||||||
fn new(names: Names) -> Self {
|
fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
names: names,
|
names: Names::new(),
|
||||||
records: Vec::new(),
|
records: VecDeque::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn len(&self) -> usize {
|
fn push(&mut self, rec: Record) -> Result<(), MTTError> {
|
||||||
0
|
if self.names.is_empty() {
|
||||||
|
self.names = rec.names;
|
||||||
|
self.records.push_back(rec.data.clone());
|
||||||
|
} else {
|
||||||
|
if rec.names != self.names {
|
||||||
|
return Err(MTTError::RecordMismatch);
|
||||||
|
}
|
||||||
|
let existing: HashSet<Uuid> = self.records.front().unwrap().keys().cloned().collect();
|
||||||
|
let rec_keys: HashSet<Uuid> = rec.data.keys().cloned().collect();
|
||||||
|
if existing == rec_keys {
|
||||||
|
self.records.push_back(rec.data.clone());
|
||||||
|
} else {
|
||||||
|
return Err(MTTError::RecordMismatch);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add<NT, F>(&mut self, name: NT, data: F) -> Result<(), MTTError> where F: Into<Field>, NT: Into<NameType> {
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get<NT>(&self, rec_num: usize, field_name: NT) -> Result<&Field, MTTError> where NT: Into<NameType> {
|
|
||||||
Err(MTTError::QueryCannotChangeData)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn submit(&mut self) {
|
|
||||||
}
|
|
||||||
|
|
||||||
fn iter(&self) -> impl Iterator<Item = usize> {
|
|
||||||
RecordsIter::new(self)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RecordsIter {
|
impl Iterator for RecordIter {
|
||||||
position: usize,
|
type Item = Record;
|
||||||
rec_count: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RecordsIter {
|
|
||||||
fn new(records: &Records) -> Self {
|
|
||||||
Self {
|
|
||||||
position: 0,
|
|
||||||
rec_count: records.len(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Iterator for RecordsIter {
|
|
||||||
type Item = usize;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
self.position += 1;
|
match self.records.pop_front() {
|
||||||
if self.position < self.rec_count {
|
Some(data) => Some(Record {
|
||||||
Some(self.position)
|
names: self.names.clone(),
|
||||||
} else {
|
data: data,
|
||||||
None
|
}),
|
||||||
|
None => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ExactSizeIterator for RecordIter {
|
||||||
|
fn len(&self) -> usize {
|
||||||
|
self.records.len()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod records {
|
mod records {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -3420,10 +3500,14 @@ mod records {
|
|||||||
assert_eq!(id1, id2, "id and name should produce the same result");
|
assert_eq!(id1, id2, "id and name should produce the same result");
|
||||||
match id1 {
|
match id1 {
|
||||||
Field::Uuid(data) => {
|
Field::Uuid(data) => {
|
||||||
assert_eq!(data.to_string(), name.to_string(), "for this case, name and data should match");
|
assert_eq!(
|
||||||
|
data.to_string(),
|
||||||
|
name.to_string(),
|
||||||
|
"for this case, name and data should match"
|
||||||
|
);
|
||||||
assert!(ids.contains(&data), "{:?} not in {:?}", id1, ids);
|
assert!(ids.contains(&data), "{:?} not in {:?}", id1, ids);
|
||||||
ids.remove(&data);
|
ids.remove(&data);
|
||||||
},
|
}
|
||||||
_ => unreachable!("got {:?}, should have been uuid", id1),
|
_ => unreachable!("got {:?}, should have been uuid", id1),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3440,7 +3524,7 @@ mod records {
|
|||||||
Err(err) => match err {
|
Err(err) => match err {
|
||||||
MTTError::NameNotFound(data) => assert_eq!(data, name),
|
MTTError::NameNotFound(data) => assert_eq!(data, name),
|
||||||
_ => unreachable!("got {:?}, should have been not found", err),
|
_ => unreachable!("got {:?}, should have been not found", err),
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3454,7 +3538,7 @@ mod records {
|
|||||||
Err(err) => match err {
|
Err(err) => match err {
|
||||||
MTTError::NameNotFound(data) => assert_eq!(data, name),
|
MTTError::NameNotFound(data) => assert_eq!(data, name),
|
||||||
_ => unreachable!("got {:?}, should have been not found", err),
|
_ => unreachable!("got {:?}, should have been not found", err),
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3467,37 +3551,77 @@ mod records {
|
|||||||
match rec.get(&name) {
|
match rec.get(&name) {
|
||||||
Ok(_) => unreachable!("should return not found error"),
|
Ok(_) => unreachable!("should return not found error"),
|
||||||
Err(err) => match err {
|
Err(err) => match err {
|
||||||
MTTError::FieldMissingData => {},
|
MTTError::FieldMissingData => {}
|
||||||
_ => unreachable!("got {:?}, should have been not found", err),
|
_ => unreachable!("got {:?}, should have been not found", err),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn can_create_empty_record() {
|
|
||||||
let rec = Records::new(Names::new());
|
|
||||||
assert_eq!(rec.len(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
fn can_records_hold_multiple_entries() {
|
||||||
fn can_have_multiple_rows() {
|
let field_name = Name::english("field".to_string());
|
||||||
let mut names = Names::new();
|
let mut names = Names::new();
|
||||||
let name = Name::english("field".to_string());
|
names.add_name(field_name.clone());
|
||||||
let mut recs = Records::new(names);
|
let count: isize = 5;
|
||||||
let data: [Field; 3] = ["one".into(), "two".into(), "three".into()];
|
let mut recs = RecordIter::new();
|
||||||
for item in data.iter() {
|
assert_eq!(recs.len(), 0, "should contain no records");
|
||||||
recs.add(&name, item.clone());
|
for data in 0..count {
|
||||||
recs.submit();
|
let mut rec = Record::new(names.clone());
|
||||||
|
rec.insert(field_name.clone(), data.clone());
|
||||||
|
recs.push(rec);
|
||||||
|
let holder: usize = (data + 1).try_into().unwrap();
|
||||||
|
assert_eq!(recs.len(), holder, "should increase the count");
|
||||||
}
|
}
|
||||||
assert_eq!(recs.len(), data.len(), "does not contain the correct number of records");
|
let mut data = 0;
|
||||||
for rec_num in recs.iter() {
|
for rec in recs {
|
||||||
assert!(data.contains(recs.get(rec_num, &name).unwrap()));
|
let item = rec.get(&field_name).unwrap();
|
||||||
|
assert_eq!(item, data.into());
|
||||||
|
data += 1;
|
||||||
|
}
|
||||||
|
assert_eq!(data, count, "did not iterate")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn errors_on_mismatched_names() {
|
||||||
|
let count = 2;
|
||||||
|
let mut recs: Vec<Record> = Vec::new();
|
||||||
|
for i in 0..count {
|
||||||
|
let name = Name::english(i.to_string());
|
||||||
|
let mut names = Names::new();
|
||||||
|
names.add_name(name);
|
||||||
|
recs.push(Record::new(names));
|
||||||
|
}
|
||||||
|
let mut rec_iter = RecordIter::new();
|
||||||
|
rec_iter.push(recs[0].clone()).unwrap();
|
||||||
|
match rec_iter.push(recs[1].clone()) {
|
||||||
|
Ok(_) => unreachable!("should have returned error"),
|
||||||
|
Err(err) => match err {
|
||||||
|
MTTError::RecordMismatch => {}
|
||||||
|
_ => unreachable!("got {:?}, should have gotten mismatched names", err),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn errors_on_mismatched_entries() {
|
||||||
|
let mut names = Names::new();
|
||||||
|
let name1 = Name::english("first".to_string());
|
||||||
|
let name2 = Name::english("second".to_string());
|
||||||
|
names.add_name(name1.clone()).unwrap();
|
||||||
|
names.add_name(name2.clone()).unwrap();
|
||||||
|
let mut rec1 = Record::new(names.clone());
|
||||||
|
rec1.insert(&name1, 1);
|
||||||
|
rec1.insert(&name2, 2);
|
||||||
|
let mut rec2 = Record::new(names.clone());
|
||||||
|
rec2.insert(&name1, 1);
|
||||||
|
let mut rec_iter = RecordIter::new();
|
||||||
|
rec_iter.push(rec1).unwrap();
|
||||||
|
match rec_iter.push(rec2) {
|
||||||
|
Ok(_) => unreachable!("should have returned error"),
|
||||||
|
Err(err) => match err {
|
||||||
|
MTTError::RecordMismatch => {}
|
||||||
|
_ => unreachable!("got {:?}, should have gotten mismatched names", err),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3522,7 +3646,10 @@ impl Document {
|
|||||||
self.data.insert(name.into(), field.into());
|
self.data.insert(name.into(), field.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_field<NT>(&self, name: NT) -> Option<Field> where NT: Into<NameType> {
|
fn get_field<NT>(&self, name: NT) -> Option<Field>
|
||||||
|
where
|
||||||
|
NT: Into<NameType>,
|
||||||
|
{
|
||||||
match self.data.get(&name.into()) {
|
match self.data.get(&name.into()) {
|
||||||
Some(data) => Some(data.get()),
|
Some(data) => Some(data.get()),
|
||||||
None => None,
|
None => None,
|
||||||
@ -4029,7 +4156,10 @@ impl DocumentFile {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
fn validate<NT>(&self, field_name: NT, value: Option<Field>) -> Result<(Uuid, Field), MTTError> where NT: Into<NameType> {
|
fn validate<NT>(&self, field_name: NT, value: Option<Field>) -> Result<(Uuid, Field), MTTError>
|
||||||
|
where
|
||||||
|
NT: Into<NameType>,
|
||||||
|
{
|
||||||
let field_id = match self.docdef.get_field_id(field_name) {
|
let field_id = match self.docdef.get_field_id(field_name) {
|
||||||
Ok(data) => data,
|
Ok(data) => data,
|
||||||
Err(err) => return Err(err),
|
Err(err) => return Err(err),
|
||||||
@ -4053,12 +4183,18 @@ impl DocumentFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_to_index<NT>(&mut self, field_name: NT, field: Field, oid: Oid) where NT: Into<NameType> {
|
fn add_to_index<NT>(&mut self, field_name: NT, field: Field, oid: Oid)
|
||||||
|
where
|
||||||
|
NT: Into<NameType>,
|
||||||
|
{
|
||||||
let field_id = self.docdef.get_field_id(field_name).unwrap();
|
let field_id = self.docdef.get_field_id(field_name).unwrap();
|
||||||
self.indexes.add_to_index(&field_id, field, oid)
|
self.indexes.add_to_index(&field_id, field, oid)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_from_index<NT>(&mut self, field_name: NT, field: &Field, oid: &Oid) where NT: Into<NameType> {
|
fn remove_from_index<NT>(&mut self, field_name: NT, field: &Field, oid: &Oid)
|
||||||
|
where
|
||||||
|
NT: Into<NameType>,
|
||||||
|
{
|
||||||
let field_id = self.docdef.get_field_id(field_name).unwrap();
|
let field_id = self.docdef.get_field_id(field_name).unwrap();
|
||||||
self.indexes.remove_from_index(&field_id, field, oid);
|
self.indexes.remove_from_index(&field_id, field, oid);
|
||||||
}
|
}
|
||||||
@ -4068,7 +4204,9 @@ impl DocumentFile {
|
|||||||
let doc = addition.get_document();
|
let doc = addition.get_document();
|
||||||
for (field, value) in doc.iter() {
|
for (field, value) in doc.iter() {
|
||||||
match self.validate(field, Some(value)) {
|
match self.validate(field, Some(value)) {
|
||||||
Ok((id, data)) => {holder.insert(id, data);},
|
Ok((id, data)) => {
|
||||||
|
holder.insert(id, data);
|
||||||
|
}
|
||||||
Err(err) => return MsgAction::Error(err),
|
Err(err) => return MsgAction::Error(err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4076,7 +4214,9 @@ impl DocumentFile {
|
|||||||
let all_fields = self.docdef.field_ids();
|
let all_fields = self.docdef.field_ids();
|
||||||
for field in all_fields.difference(&requested).cloned() {
|
for field in all_fields.difference(&requested).cloned() {
|
||||||
match self.validate(field, None) {
|
match self.validate(field, None) {
|
||||||
Ok((id, data)) => {holder.insert(id, data);},
|
Ok((id, data)) => {
|
||||||
|
holder.insert(id, data);
|
||||||
|
}
|
||||||
Err(err) => return MsgAction::Error(err),
|
Err(err) => return MsgAction::Error(err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4088,7 +4228,6 @@ impl DocumentFile {
|
|||||||
}
|
}
|
||||||
self.docs.insert(oid, holder);
|
self.docs.insert(oid, holder);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
self.docs.insert(oid.clone(), holder.clone());
|
self.docs.insert(oid.clone(), holder.clone());
|
||||||
for (key, value) in holder.iter() {
|
for (key, value) in holder.iter() {
|
||||||
@ -4096,13 +4235,9 @@ impl DocumentFile {
|
|||||||
}
|
}
|
||||||
reply.add(holder);
|
reply.add(holder);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
reply.into()
|
reply.into()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
let mut holder = Document::new();
|
let mut holder = Document::new();
|
||||||
let doc = addition.get_document();
|
let doc = addition.get_document();
|
||||||
@ -4183,10 +4318,6 @@ impl DocumentFile {
|
|||||||
}
|
}
|
||||||
Ok(oids)
|
Ok(oids)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
let query_ids = query.field_ids();
|
let query_ids = query.field_ids();
|
||||||
let doc_ids = self.docdef.field_ids();
|
let doc_ids = self.docdef.field_ids();
|
||||||
@ -4382,7 +4513,8 @@ mod document_files {
|
|||||||
let msg = Message::new(self.docdef.get_document_name().clone(), self.docdef.clone());
|
let msg = Message::new(self.docdef.get_document_name().clone(), self.docdef.clone());
|
||||||
DocumentFile::start(self.queue.clone(), msg);
|
DocumentFile::start(self.queue.clone(), msg);
|
||||||
for route in self.routes.iter() {
|
for route in self.routes.iter() {
|
||||||
let request = Register::new(self.sender_id.clone(), RegMsg::AddRoute(route.clone()));
|
let request =
|
||||||
|
Register::new(self.sender_id.clone(), RegMsg::AddRoute(route.clone()));
|
||||||
let add_route = Message::new(NameType::None, request);
|
let add_route = Message::new(NameType::None, request);
|
||||||
self.queue.send(add_route).unwrap();
|
self.queue.send(add_route).unwrap();
|
||||||
self.rx.recv().unwrap();
|
self.rx.recv().unwrap();
|
||||||
@ -4495,9 +4627,16 @@ mod document_files {
|
|||||||
Ok(data) => data.clone(),
|
Ok(data) => data.clone(),
|
||||||
Err(err) => unreachable!("for {:?} got {:?}", msg_action, err),
|
Err(err) => unreachable!("for {:?} got {:?}", msg_action, err),
|
||||||
};
|
};
|
||||||
assert_eq!(result.get_message_id(), msg.get_message_id(), "for {:?} response and reply ids should equal", msg_action);
|
assert_eq!(
|
||||||
|
result.get_message_id(),
|
||||||
|
msg.get_message_id(),
|
||||||
|
"for {:?} response and reply ids should equal",
|
||||||
|
msg_action
|
||||||
|
);
|
||||||
match result.get_action() {
|
match result.get_action() {
|
||||||
MsgAction::Reply(data) => assert_eq!(data.len(), 0, "for {:?} got {:?}", msg_action, result),
|
MsgAction::Reply(data) => {
|
||||||
|
assert_eq!(data.len(), 0, "for {:?} got {:?}", msg_action, result)
|
||||||
|
}
|
||||||
_ => unreachable!(
|
_ => unreachable!(
|
||||||
"for {:?} got {:?}: should have received a reply",
|
"for {:?} got {:?}: should have received a reply",
|
||||||
msg_action,
|
msg_action,
|
||||||
@ -4571,7 +4710,10 @@ mod document_files {
|
|||||||
None => unreachable!("{:?} did not contain field '{:?}'", holder, name),
|
None => unreachable!("{:?} did not contain field '{:?}'", holder, name),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => unreachable!("\n\ngot {:?}\n\nfor {:?}\n\nshould have been a reply", result, docdef),
|
_ => unreachable!(
|
||||||
|
"\n\ngot {:?}\n\nfor {:?}\n\nshould have been a reply",
|
||||||
|
result, docdef
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user