Rebuilt record to include field names.
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 1s

This commit is contained in:
Jeff Baskin 2025-10-13 14:13:10 -04:00
parent 96ac523898
commit 7755947816

View File

@ -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());