Rebuilt record to include field names.
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
96ac523898
commit
7755947816
354
src/message.rs
354
src/message.rs
@ -27,6 +27,7 @@ enum MTTError {
|
||||
DocumentFieldWrongDataType(FieldType, FieldType),
|
||||
DocumentNotFound(String),
|
||||
FieldDuplicate(String, Field),
|
||||
FieldMissingData,
|
||||
NameDuplicate(Name),
|
||||
NameInvalidID(Uuid),
|
||||
NameMissingTranslation(Language),
|
||||
@ -237,6 +238,7 @@ struct Message {
|
||||
msg_id: Uuid,
|
||||
document_id: NameType,
|
||||
action: MsgAction,
|
||||
// session: Option<?>
|
||||
}
|
||||
|
||||
impl Message {
|
||||
@ -752,7 +754,6 @@ mod names {
|
||||
let id = names.add_name(english.clone()).unwrap();
|
||||
let result = names.add_translation(english, japanese.clone()).unwrap();
|
||||
assert_eq!(result, id);
|
||||
println!("\n{:?}", names);
|
||||
let output = names.get_name(&id, &Language::from_639_1("ja").unwrap());
|
||||
assert_eq!(output.unwrap().to_string(), alt);
|
||||
assert_eq!(names.get_id(&japanese).unwrap(), id);
|
||||
@ -2378,6 +2379,14 @@ impl DocDef {
|
||||
&self.doc_name
|
||||
}
|
||||
|
||||
fn get_field_names(&self) -> &Names {
|
||||
&self.field_names
|
||||
}
|
||||
|
||||
fn get_field_names_mut(&mut self) -> &mut Names {
|
||||
&mut self.field_names
|
||||
}
|
||||
|
||||
fn add_field(&mut self, name: Name, ftype: FieldType) {
|
||||
let id = self.field_names.add_name(name).unwrap();
|
||||
self.fields.insert(id, FieldSetting::new(ftype));
|
||||
@ -2406,9 +2415,8 @@ impl DocDef {
|
||||
Ok(self.fields.get_mut(&id).unwrap())
|
||||
}
|
||||
|
||||
fn field_ids(&self) -> HashSet<&Uuid> {
|
||||
self.fields.keys().collect()
|
||||
//self.fields.keys().cloned().collect::<HashSet<String>>()
|
||||
fn field_ids(&self) -> HashSet<Uuid> {
|
||||
self.fields.keys().cloned().collect()
|
||||
}
|
||||
|
||||
fn validate<NT>(&self, field_name: NT, value: Option<Field>) -> Result<Field, MTTError> where NT: Into<NameType> {
|
||||
@ -2417,15 +2425,6 @@ impl DocDef {
|
||||
Err(err) => return Err(err),
|
||||
};
|
||||
self.fields.get(&id).unwrap().validate(value)
|
||||
|
||||
|
||||
/*
|
||||
let setting = match self.get_field(field_name) {
|
||||
Ok(data) => data,
|
||||
Err(err) => return Err(err),
|
||||
};
|
||||
setting.validate(value)
|
||||
*/
|
||||
}
|
||||
|
||||
fn set_default(&mut self, field_name: &Name, value: Calculation) -> Result<(), MTTError> {
|
||||
@ -3296,6 +3295,213 @@ mod replies {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct Record {
|
||||
names: Names,
|
||||
data: HashMap<Uuid, Field>
|
||||
}
|
||||
|
||||
impl Record {
|
||||
fn new(names: Names) -> Self {
|
||||
Self {
|
||||
names: names,
|
||||
data: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
Ok(data) => data,
|
||||
Err(err) => return Err(err),
|
||||
};
|
||||
self.data.insert(id, data.into());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
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::FieldMissingData),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct Records {
|
||||
names: Names,
|
||||
records: Vec<Record>,
|
||||
}
|
||||
|
||||
impl Records {
|
||||
fn new(names: Names) -> Self {
|
||||
Self {
|
||||
names: names,
|
||||
records: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn len(&self) -> usize {
|
||||
0
|
||||
}
|
||||
|
||||
fn add<NT, F>(&mut self, name: NT, data: F) -> Result<(), MTTError> where F: Into<Field>, NT: Into<NameType> {
|
||||
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 {
|
||||
position: usize,
|
||||
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> {
|
||||
self.position += 1;
|
||||
if self.position < self.rec_count {
|
||||
Some(self.position)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod records {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn can_create_a_record() {
|
||||
let mut names = Names::new();
|
||||
let count = 5;
|
||||
let mut ids: HashSet<Uuid> = HashSet::new();
|
||||
while ids.len() < count {
|
||||
ids.insert(Uuid::new_v4());
|
||||
}
|
||||
let mut name_ids: HashMap<Name, Uuid> = HashMap::new();
|
||||
for id in ids.iter() {
|
||||
let name = Name::english(id.to_string());
|
||||
let field_id = names.add_name(name.clone()).unwrap();
|
||||
name_ids.insert(name, field_id);
|
||||
}
|
||||
let mut rec = Record::new(names);
|
||||
for id in ids.iter() {
|
||||
let name = Name::english(id.to_string());
|
||||
rec.insert(name, id.clone());
|
||||
}
|
||||
for (name, id) in name_ids.iter() {
|
||||
let id1 = rec.get(name).unwrap();
|
||||
let id2 = rec.get(id).unwrap();
|
||||
assert_eq!(id1, id2, "id and name should produce the same result");
|
||||
match id1 {
|
||||
Field::Uuid(data) => {
|
||||
assert_eq!(data.to_string(), name.to_string(), "for this case, name and data should match");
|
||||
assert!(ids.contains(&data), "{:?} not in {:?}", id1, ids);
|
||||
ids.remove(&data);
|
||||
},
|
||||
_ => unreachable!("got {:?}, should have been uuid", id1),
|
||||
}
|
||||
}
|
||||
assert_eq!(ids.len(), 0, "did not pull {:?}", ids);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn does_insert_error_on_bad_field_name() {
|
||||
let names = Names::new();
|
||||
let mut rec = Record::new(names);
|
||||
let name = Name::english("wrong".to_string());
|
||||
match rec.insert(name.clone(), "bad") {
|
||||
Ok(_) => unreachable!("should return not found error"),
|
||||
Err(err) => match err {
|
||||
MTTError::NameNotFound(data) => assert_eq!(data, name),
|
||||
_ => unreachable!("got {:?}, should have been not found", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn does_get_error_on_bad_field_name() {
|
||||
let names = Names::new();
|
||||
let mut rec = Record::new(names);
|
||||
let name = Name::english("missing".to_string());
|
||||
match rec.get(&name) {
|
||||
Ok(_) => unreachable!("should return not found error"),
|
||||
Err(err) => match err {
|
||||
MTTError::NameNotFound(data) => assert_eq!(data, name),
|
||||
_ => unreachable!("got {:?}, should have been not found", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn does_get_error_on_missing_data() {
|
||||
let mut names = Names::new();
|
||||
let name = Name::english("empty".to_string());
|
||||
names.add_name(name.clone()).unwrap();
|
||||
let mut rec = Record::new(names);
|
||||
match rec.get(&name) {
|
||||
Ok(_) => unreachable!("should return not found error"),
|
||||
Err(err) => match err {
|
||||
MTTError::FieldMissingData => {},
|
||||
_ => 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]
|
||||
#[ignore]
|
||||
fn can_have_multiple_rows() {
|
||||
let mut names = Names::new();
|
||||
let name = Name::english("field".to_string());
|
||||
let mut recs = Records::new(names);
|
||||
let data: [Field; 3] = ["one".into(), "two".into(), "three".into()];
|
||||
for item in data.iter() {
|
||||
recs.add(&name, item.clone());
|
||||
recs.submit();
|
||||
}
|
||||
assert_eq!(recs.len(), data.len(), "does not contain the correct number of records");
|
||||
for rec_num in recs.iter() {
|
||||
assert!(data.contains(recs.get(rec_num, &name).unwrap()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct Document {
|
||||
data: HashMap<NameType, CalcValue>,
|
||||
@ -3334,6 +3540,10 @@ impl Document {
|
||||
fn iter(&self) -> DocIter {
|
||||
DocIter::new(self)
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
self.data.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
struct DocIter {
|
||||
@ -3724,7 +3934,7 @@ mod indexes {
|
||||
|
||||
struct DocumentFile {
|
||||
docdef: DocDef,
|
||||
docs: HashMap<Oid, Document>,
|
||||
docs: HashMap<Oid, HashMap<Uuid, Field>>,
|
||||
indexes: Indexes,
|
||||
queue: Queue,
|
||||
rx: Receiver<Message>,
|
||||
@ -3813,11 +4023,13 @@ impl DocumentFile {
|
||||
&self.docdef
|
||||
}
|
||||
|
||||
/*
|
||||
fn get_documents<'a>(&self) -> impl Iterator<Item = (&Oid, &Document)> {
|
||||
self.docs.iter()
|
||||
}
|
||||
*/
|
||||
|
||||
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<(Uuid, Field), MTTError> where NT: Into<NameType> {
|
||||
let field_id = match self.docdef.get_field_id(field_name) {
|
||||
Ok(data) => data,
|
||||
Err(err) => return Err(err),
|
||||
@ -3830,7 +4042,7 @@ impl DocumentFile {
|
||||
Ok(_) => {}
|
||||
Err(err) => return Err(err),
|
||||
}
|
||||
Ok(output)
|
||||
Ok((field_id, output))
|
||||
}
|
||||
|
||||
fn add_field_to_error(key: String, err: MTTError) -> MTTError {
|
||||
@ -3852,6 +4064,46 @@ impl DocumentFile {
|
||||
}
|
||||
|
||||
fn add_document(&mut self, addition: &Addition) -> MsgAction {
|
||||
let mut holder: HashMap<Uuid, Field> = HashMap::new();
|
||||
let doc = addition.get_document();
|
||||
for (field, value) in doc.iter() {
|
||||
match self.validate(field, Some(value)) {
|
||||
Ok((id, data)) => {holder.insert(id, data);},
|
||||
Err(err) => return MsgAction::Error(err),
|
||||
}
|
||||
}
|
||||
let requested: HashSet<Uuid> = holder.keys().cloned().collect();
|
||||
let all_fields = self.docdef.field_ids();
|
||||
for field in all_fields.difference(&requested).cloned() {
|
||||
match self.validate(field, None) {
|
||||
Ok((id, data)) => {holder.insert(id, data);},
|
||||
Err(err) => return MsgAction::Error(err),
|
||||
}
|
||||
}
|
||||
let mut reply = Reply::new();
|
||||
if !holder.is_empty() {
|
||||
let mut oid = Oid::new();
|
||||
while self.docs.contains_key(&oid) {
|
||||
oid = Oid::new();
|
||||
}
|
||||
self.docs.insert(oid, holder);
|
||||
|
||||
|
||||
/*
|
||||
self.docs.insert(oid.clone(), holder.clone());
|
||||
for (key, value) in holder.iter() {
|
||||
self.add_to_index(&key, value.clone(), oid.clone());
|
||||
}
|
||||
reply.add(holder);
|
||||
*/
|
||||
|
||||
|
||||
}
|
||||
reply.into()
|
||||
|
||||
|
||||
|
||||
/*
|
||||
let mut holder = Document::new();
|
||||
let doc = addition.get_document();
|
||||
for (key, value) in doc.iter() {
|
||||
@ -3872,25 +4124,30 @@ impl DocumentFile {
|
||||
}
|
||||
}
|
||||
let mut oid = Oid::new();
|
||||
while self.docs.contains_key(&oid) {
|
||||
oid = Oid::new();
|
||||
}
|
||||
self.docs.insert(oid.clone(), holder.clone());
|
||||
for (key, value) in holder.iter() {
|
||||
self.add_to_index(&key, value.clone(), oid.clone());
|
||||
}
|
||||
let mut reply = Reply::new();
|
||||
reply.add(holder);
|
||||
if !holder.is_empty() {
|
||||
while self.docs.contains_key(&oid) {
|
||||
oid = Oid::new();
|
||||
}
|
||||
self.docs.insert(oid.clone(), holder.clone());
|
||||
for (key, value) in holder.iter() {
|
||||
self.add_to_index(&key, value.clone(), oid.clone());
|
||||
}
|
||||
reply.add(holder);
|
||||
}
|
||||
reply.into()
|
||||
*/
|
||||
}
|
||||
|
||||
fn delete(&mut self, delete: &Delete) -> MsgAction {
|
||||
let mut reply = Reply::new();
|
||||
/*
|
||||
let oids = self.run_query(delete.get_query()).unwrap();
|
||||
for oid in oids.iter() {
|
||||
reply.add(self.docs.get(oid).unwrap().clone());
|
||||
self.docs.remove(oid);
|
||||
}
|
||||
*/
|
||||
reply.into()
|
||||
}
|
||||
|
||||
@ -3915,11 +4172,10 @@ impl DocumentFile {
|
||||
oids = oids.intersection(&holder).cloned().collect();
|
||||
}
|
||||
for (field_id, calculation) in unindexed.iter() {
|
||||
let mut holder: HashSet<Oid> = HashSet::new();
|
||||
for oid in oids.clone().iter() {
|
||||
let doc = self.docs.get(oid).unwrap();
|
||||
let mut calc = calculation.clone();
|
||||
calc.add_value(doc.get_field(field_id).unwrap());
|
||||
calc.add_value(doc.get(field_id).unwrap().clone());
|
||||
if calc.calculate() == false.into() {
|
||||
oids.remove(oid);
|
||||
}
|
||||
@ -4002,7 +4258,7 @@ impl DocumentFile {
|
||||
Ok(result) => {
|
||||
let mut reply = Reply::new();
|
||||
for oid in result.iter() {
|
||||
reply.add(self.docs.get(oid).unwrap().clone());
|
||||
//reply.add(self.docs.get(oid).unwrap().clone());
|
||||
}
|
||||
reply.into()
|
||||
}
|
||||
@ -4011,6 +4267,7 @@ impl DocumentFile {
|
||||
}
|
||||
|
||||
fn update(&mut self, update: &Update) -> MsgAction {
|
||||
/*
|
||||
let oids = match self.run_query(update.get_query()) {
|
||||
Ok(result) => result,
|
||||
Err(err) => return err.into(),
|
||||
@ -4050,6 +4307,8 @@ impl DocumentFile {
|
||||
}
|
||||
}
|
||||
reply.into()
|
||||
*/
|
||||
Reply::new().into()
|
||||
}
|
||||
}
|
||||
|
||||
@ -4223,8 +4482,11 @@ mod document_files {
|
||||
test_doc.start();
|
||||
let queue = test_doc.get_queue();
|
||||
let msg_actions = [
|
||||
MsgAction::Show,
|
||||
MsgAction::Addition(Addition::new()),
|
||||
MsgAction::Delete(Delete::new()),
|
||||
MsgAction::Query(Query::new()),
|
||||
MsgAction::Show,
|
||||
MsgAction::Update(Update::new()),
|
||||
];
|
||||
for msg_action in msg_actions.iter() {
|
||||
let msg = Message::new(name.clone(), msg_action.clone());
|
||||
@ -4235,7 +4497,7 @@ mod document_files {
|
||||
};
|
||||
assert_eq!(result.get_message_id(), msg.get_message_id(), "for {:?} response and reply ids should equal", msg_action);
|
||||
match result.get_action() {
|
||||
MsgAction::Reply(data) => assert_eq!(data.len(), 0),
|
||||
MsgAction::Reply(data) => assert_eq!(data.len(), 0, "for {:?} got {:?}", msg_action, result),
|
||||
_ => unreachable!(
|
||||
"for {:?} got {:?}: should have received a reply",
|
||||
msg_action,
|
||||
@ -4258,8 +4520,11 @@ mod document_files {
|
||||
queue.send(setup).unwrap();
|
||||
test_doc.get_receiver().recv_timeout(TIMEOUT).unwrap();
|
||||
let msg_actions = [
|
||||
MsgAction::Show,
|
||||
MsgAction::Addition(Addition::new()),
|
||||
MsgAction::Delete(Delete::new()),
|
||||
MsgAction::Query(Query::new()),
|
||||
MsgAction::Show,
|
||||
MsgAction::Update(Update::new()),
|
||||
];
|
||||
for msg_action in msg_actions.iter() {
|
||||
let msg = Message::new(alt.clone(), msg_action.clone());
|
||||
@ -4275,12 +4540,39 @@ mod document_files {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn can_document_be_added() {
|
||||
let doc_name = Name::english("document".to_string());
|
||||
let mut docdef = DocDef::new(doc_name.clone());
|
||||
let name = Name::english("field".to_string());
|
||||
let data = Uuid::new_v4();
|
||||
docdef.add_field(name, FieldType::Uuid);
|
||||
docdef.add_field(name.clone(), FieldType::Uuid);
|
||||
let mut test_doc: TestDocument = docdef.clone().into();
|
||||
test_doc.start();
|
||||
let queue = test_doc.get_queue();
|
||||
let mut new_doc = Addition::new();
|
||||
new_doc.add_field(name.clone(), data.clone());
|
||||
let msg = Message::new(doc_name, new_doc);
|
||||
queue.send(msg.clone()).unwrap();
|
||||
let result = test_doc.get_receiver().recv_timeout(TIMEOUT).unwrap();
|
||||
assert_eq!(result.get_message_id(), msg.get_message_id());
|
||||
match result.get_action() {
|
||||
MsgAction::Reply(output) => {
|
||||
assert_eq!(output.len(), 1);
|
||||
let holder = output.iter().next().unwrap();
|
||||
match holder.get_field(name.clone()) {
|
||||
Some(field) => match field {
|
||||
Field::Uuid(store) => assert_eq!(store, data),
|
||||
_ => unreachable!(
|
||||
"got {:?}: should have received uuid",
|
||||
holder.get_field(name).unwrap()
|
||||
),
|
||||
},
|
||||
None => unreachable!("{:?} did not contain field '{:?}'", holder, name),
|
||||
}
|
||||
}
|
||||
_ => unreachable!("\n\ngot {:?}\n\nfor {:?}\n\nshould have been a reply", result, docdef),
|
||||
}
|
||||
|
||||
/*
|
||||
let (queue, rx) = test_doc(doc_name, docdef, standard_routes());
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user