diff --git a/libdonet/src/dcarray.rs b/libdonet/src/dcarray.rs index 1abffdd..b75dc5b 100644 --- a/libdonet/src/dcarray.rs +++ b/libdonet/src/dcarray.rs @@ -20,7 +20,7 @@ use crate::dctype::{DCTypeDefinition, DCTypeDefinitionInterface, DCTypeEnum}; use crate::hashgen::DCHashGenerator; pub struct DCArrayType { - _dcarray_parent: DCTypeDefinition, + base_type: DCTypeDefinition, element_type: Option, array_size: u16, array_range: Option, @@ -40,7 +40,7 @@ pub trait DCArrayTypeInterface { impl DCArrayTypeInterface for DCArrayType { fn new(element_type: Option, size: Option) -> Self { let mut new_array_type: Self = Self { - _dcarray_parent: DCTypeDefinition::new(), + base_type: DCTypeDefinition::new(), element_type: element_type, array_size: 0_u16, array_range: size, @@ -65,27 +65,27 @@ impl DCArrayTypeInterface for DCArrayType { if new_array_type.element_type.is_some() { let e_type: DCTypeDefinition = new_array_type.element_type.clone().unwrap(); - if !e_type.is_variable_length() && new_array_type.size > 0 { - new_array_type.data_type = DCTypeEnum::TArray; - new_array_type.size = new_array_type.array_size * e_type.get_size(); + if !e_type.is_variable_length() && new_array_type.base_type.size > 0 { + new_array_type.base_type.data_type = DCTypeEnum::TArray; + new_array_type.base_type.size = new_array_type.array_size * e_type.get_size(); } else { - new_array_type.data_type = DCTypeEnum::TVarArray; - new_array_type.size = 0_u16; + new_array_type.base_type.data_type = DCTypeEnum::TVarArray; + new_array_type.base_type.size = 0_u16; } match e_type.get_dc_type() { DCTypeEnum::TChar => { - if new_array_type.data_type == DCTypeEnum::TArray { - new_array_type.data_type = DCTypeEnum::TString; + if new_array_type.base_type.data_type == DCTypeEnum::TArray { + new_array_type.base_type.data_type = DCTypeEnum::TString; } else { - new_array_type.data_type = DCTypeEnum::TVarString; + new_array_type.base_type.data_type = DCTypeEnum::TVarString; } } DCTypeEnum::TUInt8 => { - if new_array_type.data_type == DCTypeEnum::TArray { - new_array_type.data_type = DCTypeEnum::TBlob; + if new_array_type.base_type.data_type == DCTypeEnum::TArray { + new_array_type.base_type.data_type = DCTypeEnum::TBlob; } else { - new_array_type.data_type = DCTypeEnum::TVarBlob; + new_array_type.base_type.data_type = DCTypeEnum::TVarBlob; } } _ => {} @@ -95,17 +95,17 @@ impl DCArrayTypeInterface for DCArrayType { } fn generate_hash(&self, hashgen: &mut DCHashGenerator) { - self.dctype_generate_hash(hashgen); + self.base_type.generate_hash(hashgen); if let Some(element_type) = self.element_type.clone() { - element_type.dctype_generate_hash(hashgen); + element_type.generate_hash(hashgen); } else { // Since we don't have an element type (representing // an 'invalid' element type, if comparing to Astron src) // we just make a new empty DCTypeDefinition, since that // is what Astron's DistributedType::invalid equals to. let empty_dc_type: DCTypeDefinition = DCTypeDefinition::new(); - empty_dc_type.dctype_generate_hash(hashgen); + empty_dc_type.generate_hash(hashgen); } if self.has_range() { // TODO! @@ -116,7 +116,7 @@ impl DCArrayTypeInterface for DCArrayType { } fn get_array_size(&self) -> u16 { - self.size + self.base_type.size } fn get_element_type(&self) -> Option { self.element_type.clone() @@ -128,20 +128,3 @@ impl DCArrayTypeInterface for DCArrayType { self.array_range.is_some() } } - -/// By manually implementing/overriding the standard -/// library's 'Deref' trait of our 'child' struct, we -/// can implicitly cast pointers to the parent struct, -/// as pointers to the child struct, which gives us a -/// nice 'cheat' for the feel of inheritance. -impl std::ops::Deref for DCArrayType { - type Target = DCTypeDefinition; - fn deref(&self) -> &Self::Target { - &self._dcarray_parent - } -} -impl std::ops::DerefMut for DCArrayType { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self._dcarray_parent - } -} diff --git a/libdonet/src/dcatomic.rs b/libdonet/src/dcatomic.rs index 436dc06..5f9e441 100644 --- a/libdonet/src/dcatomic.rs +++ b/libdonet/src/dcatomic.rs @@ -27,7 +27,7 @@ use std::sync::{Arc, Mutex}; /// always implemented as a remote procedure call (RPC). #[derive(Debug)] pub struct DCAtomicField { - _dcatomicfield_parent: DCField, + base_field: DCField, elements: Vec>>, } @@ -44,7 +44,7 @@ pub trait DCAtomicFieldInterface { impl DCAtomicFieldInterface for DCAtomicField { fn new(name: &str, dclass: Arc>, bogus_field: bool) -> Self { Self { - _dcatomicfield_parent: { + base_field: { let mut new_dcfield = DCField::new(name, DCTypeDefinition::new()); new_dcfield.set_parent_dclass(dclass); new_dcfield.set_bogus_field(bogus_field); @@ -55,7 +55,7 @@ impl DCAtomicFieldInterface for DCAtomicField { } fn generate_hash(&self, hashgen: &mut DCHashGenerator) { - self._dcatomicfield_parent.dcfield_generate_hash(hashgen); + self.base_field.generate_hash(hashgen); // TODO! } @@ -74,11 +74,3 @@ impl DCAtomicFieldInterface for DCAtomicField { self.elements.push(Arc::new(Mutex::new(element))); } } - -/// See issue #22. -impl std::ops::Deref for DCAtomicField { - type Target = DCField; - fn deref(&self) -> &Self::Target { - &self._dcatomicfield_parent - } -} diff --git a/libdonet/src/dcattribute.rs b/libdonet/src/dcattribute.rs index 28a2a3f..0f43183 100644 --- a/libdonet/src/dcattribute.rs +++ b/libdonet/src/dcattribute.rs @@ -15,7 +15,9 @@ // along with this program; if not, write to the Free Software Foundation, // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -use crate::dcfield::DCField; +use crate::dcfield::{DCField, DCFieldInterface}; +use crate::dctype::DCTypeDefinition; +use crate::hashgen::DCHashGenerator; /// A DC Attribute Field is a type of DC Field which can be found /// in DC Structs and Distributed Classes. @@ -26,13 +28,22 @@ use crate::dcfield::DCField; /// do not carry DC Keywords, but their corresponding DC Atomic Field does. #[derive(Debug)] pub struct DCAttributeField { - _dcattributefield_parent: DCField, + base_field: DCField, } -/// See issue #22. -impl std::ops::Deref for DCAttributeField { - type Target = DCField; - fn deref(&self) -> &Self::Target { - &self._dcattributefield_parent +pub trait DCAttributeFieldInterface { + fn new(name: &str, dtype: DCTypeDefinition) -> Self; + fn generate_hash(&self, hashgen: &mut DCHashGenerator); +} + +impl DCAttributeFieldInterface for DCAttributeField { + fn new(name: &str, dtype: DCTypeDefinition) -> Self { + Self { + base_field: DCField::new(name, dtype), + } + } + + fn generate_hash(&self, hashgen: &mut DCHashGenerator) { + self.base_field.generate_hash(hashgen); } } diff --git a/libdonet/src/dcfield.rs b/libdonet/src/dcfield.rs index ad494d5..2c1d5e2 100644 --- a/libdonet/src/dcfield.rs +++ b/libdonet/src/dcfield.rs @@ -32,7 +32,7 @@ use std::sync::{Arc, Mutex}; /// of field declarations, which are: attribute, atomic, and molecular. #[derive(Debug)] pub struct DCField { - _dcfield_parent: DCKeywordList, + keyword_list: DCKeywordList, dclass: Option>>, _struct: Option>>, // needs '_' due to reserved keyword field_name: String, @@ -77,7 +77,7 @@ pub enum StructField { pub trait DCFieldInterface { fn new(name: &str, dtype: DCTypeDefinition) -> Self; - fn dcfield_generate_hash(&self, hashgen: &mut DCHashGenerator); + fn generate_hash(&self, hashgen: &mut DCHashGenerator); fn get_field_id(&self) -> globals::FieldId; fn get_dclass(&self) -> Arc>; @@ -113,10 +113,19 @@ impl DCField { } } +/// Macro for Panda historical keywords inline functions. +macro_rules! has_keyword { + ($self:ident, $i:literal) => { + $self + .keyword_list + .has_keyword(IdentifyKeyword::ByName($i.to_owned())) + }; +} + impl DCFieldInterface for DCField { fn new(name: &str, dtype: DCTypeDefinition) -> Self { Self { - _dcfield_parent: DCKeywordList::new(), + keyword_list: DCKeywordList::new(), dclass: None, _struct: None, field_name: name.to_owned(), @@ -130,20 +139,22 @@ impl DCFieldInterface for DCField { } } - fn dcfield_generate_hash(&self, hashgen: &mut DCHashGenerator) { - self.dckeywordlist_generate_hash(hashgen); + fn generate_hash(&self, hashgen: &mut DCHashGenerator) { + self.keyword_list.generate_hash(hashgen); + self.field_type.generate_hash(hashgen); + // It shouldn't be necessary to explicitly add the field ID // to the hash--this is computed based on the relative // position of this field with the other fields, so // adding it explicitly will be redundant. However, // the field name is significant. hashgen.add_string(self.field_name.clone()); + // The field ID is added to the hash here, since we need to ensure // the hash code comes out different in the DC_MULTIPLE_INHERITANCE case. if globals::DC_MULTIPLE_INHERITANCE { hashgen.add_int(u32::from(self.field_id)); } - self.field_type.dctype_generate_hash(hashgen); } #[inline(always)] @@ -207,55 +218,46 @@ impl DCFieldInterface for DCField { #[inline(always)] fn is_required(&self) -> bool { - self.has_keyword(IdentifyKeyword::ByName("required".to_owned())) + has_keyword!(self, "required") } #[inline(always)] fn is_broadcast(&self) -> bool { - self.has_keyword(IdentifyKeyword::ByName("broadcast".to_owned())) + has_keyword!(self, "broadcast") } #[inline(always)] fn is_ram(&self) -> bool { - self.has_keyword(IdentifyKeyword::ByName("ram".to_owned())) + has_keyword!(self, "ram") } #[inline(always)] fn is_db(&self) -> bool { - self.has_keyword(IdentifyKeyword::ByName("db".to_owned())) + has_keyword!(self, "db") } #[inline(always)] fn is_clsend(&self) -> bool { - self.has_keyword(IdentifyKeyword::ByName("clsend".to_owned())) + has_keyword!(self, "clsend") } #[inline(always)] fn is_clrecv(&self) -> bool { - self.has_keyword(IdentifyKeyword::ByName("clrecv".to_owned())) + has_keyword!(self, "clrecv") } #[inline(always)] fn is_ownsend(&self) -> bool { - self.has_keyword(IdentifyKeyword::ByName("ownsend".to_owned())) + has_keyword!(self, "ownsend") } #[inline(always)] fn is_ownrecv(&self) -> bool { - self.has_keyword(IdentifyKeyword::ByName("ownrecv".to_owned())) + has_keyword!(self, "ownrecv") } #[inline(always)] fn is_airecv(&self) -> bool { - self.has_keyword(IdentifyKeyword::ByName("airecv".to_owned())) - } -} - -/// 'Fake' inheritance of DCKeywordList object. -/// See issue #22. -impl std::ops::Deref for DCField { - type Target = DCKeywordList; - fn deref(&self) -> &Self::Target { - &self._dcfield_parent + has_keyword!(self, "airecv") } } diff --git a/libdonet/src/dckeyword.rs b/libdonet/src/dckeyword.rs index bba2188..02e9429 100644 --- a/libdonet/src/dckeyword.rs +++ b/libdonet/src/dckeyword.rs @@ -94,7 +94,7 @@ pub struct DCKeywordList { pub trait DCKeywordListInterface { fn new() -> Self; - fn dckeywordlist_generate_hash(&self, hashgen: &mut DCHashGenerator); + fn generate_hash(&self, hashgen: &mut DCHashGenerator); fn add_keyword(&mut self, keyword: DCKeyword) -> Result<(), ()>; fn get_num_keywords(&self) -> usize; @@ -126,7 +126,7 @@ impl DCKeywordListInterface for DCKeywordList { Self::default() } - fn dckeywordlist_generate_hash(&self, hashgen: &mut DCHashGenerator) { + fn generate_hash(&self, hashgen: &mut DCHashGenerator) { if self.flags != !0 { // All of the flags are historical flags only, so add just the flags // bitmask to keep the hash code the same as it has historically been. diff --git a/libdonet/src/dclass.rs b/libdonet/src/dclass.rs index 23629f7..9a30359 100644 --- a/libdonet/src/dclass.rs +++ b/libdonet/src/dclass.rs @@ -16,6 +16,7 @@ // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. use crate::dcatomic::{DCAtomicField, DCAtomicFieldInterface}; +use crate::dcattribute::DCAttributeFieldInterface; use crate::dcfield::ClassField; use crate::globals; use crate::hashgen::DCHashGenerator; @@ -97,7 +98,7 @@ impl DClassInterface for DClass { let field: MutexGuard<'_, ClassField> = new_ptr.deref().lock().unwrap(); match &field.deref() { - ClassField::Attribute(_) => todo!(), + ClassField::Attribute(attribute) => attribute.generate_hash(hashgen), ClassField::Atomic(atomic) => atomic.generate_hash(hashgen), ClassField::Molecular(_) => todo!(), } diff --git a/libdonet/src/dcmolecular.rs b/libdonet/src/dcmolecular.rs index 24b9423..57805e0 100644 --- a/libdonet/src/dcmolecular.rs +++ b/libdonet/src/dcmolecular.rs @@ -19,13 +19,5 @@ use crate::dcfield::DCField; #[derive(Debug)] pub struct DCMolecularField { - _dcmolecularfield_parent: DCField, -} - -/// See issue #22. -impl std::ops::Deref for DCMolecularField { - type Target = DCField; - fn deref(&self) -> &Self::Target { - &self._dcmolecularfield_parent - } + base_field: DCField, } diff --git a/libdonet/src/dcnumeric.rs b/libdonet/src/dcnumeric.rs index 3fe77d4..a094587 100644 --- a/libdonet/src/dcnumeric.rs +++ b/libdonet/src/dcnumeric.rs @@ -100,7 +100,7 @@ impl DCNumericRange { // ---------- Numeric Type ---------- // pub struct DCNumericType { - _dcnumeric_parent: DCTypeDefinition, + base_type: DCTypeDefinition, divisor: u16, // These are the original range and modulus values from the file, unscaled by the divisor. orig_modulus: f64, @@ -132,7 +132,7 @@ impl DCNumericType { fn data_to_number(&self, data: Vec) -> (bool, DCNumber) { // NOTE: See 'Deref' trait implementation for 'DCNumericType' below // on how we're using self.parent.size as self.size. - if self.size != data.len().try_into().unwrap() { + if self.base_type.size != data.len().try_into().unwrap() { return (false, DCNumber::new_integer(0_i64)); } @@ -140,7 +140,7 @@ impl DCNumericType { let _ = dg.add_data(data); let mut dgi = DatagramIterator::new(dg); - match self.data_type { + match self.base_type.data_type { DCTypeEnum::TInt8 => (true, DCNumber::new_integer(i64::from(dgi.read_i8()))), DCTypeEnum::TInt16 => (true, DCNumber::new_integer(i64::from(dgi.read_i16()))), DCTypeEnum::TInt32 => (true, DCNumber::new_integer(i64::from(dgi.read_i32()))), @@ -161,7 +161,7 @@ impl DCNumericType { impl DCNumericTypeInterface for DCNumericType { fn new(base_type: DCTypeEnum) -> Self { Self { - _dcnumeric_parent: { + base_type: { let mut parent_struct = DCTypeDefinition::new(); parent_struct.data_type = base_type; @@ -202,7 +202,7 @@ impl DCNumericTypeInterface for DCNumericType { } fn generate_hash(&self, hashgen: &mut DCHashGenerator) { - self.dctype_generate_hash(hashgen); + self.base_type.generate_hash(hashgen); hashgen.add_int(u32::from(self.divisor)); if self.has_modulus() { @@ -259,16 +259,3 @@ impl DCNumericTypeInterface for DCNumericType { todo!(); } } - -/* By manually implementing/overriding the standard - * library's 'Deref' trait of our 'child' struct, we - * can implicitly cast pointers to the parent struct, - * as pointers to the child struct, which gives us a - * nice 'cheat' for the feel of inheritance. - */ -impl std::ops::Deref for DCNumericType { - type Target = DCTypeDefinition; - fn deref(&self) -> &Self::Target { - &self._dcnumeric_parent - } -} diff --git a/libdonet/src/dctype.rs b/libdonet/src/dctype.rs index 46d61a8..16b94a1 100644 --- a/libdonet/src/dctype.rs +++ b/libdonet/src/dctype.rs @@ -52,7 +52,7 @@ pub struct DCTypeDefinition { pub trait DCTypeDefinitionInterface { fn new() -> Self; - fn dctype_generate_hash(&self, hashgen: &mut DCHashGenerator); + fn generate_hash(&self, hashgen: &mut DCHashGenerator); fn get_dc_type(&self) -> DCTypeEnum; fn is_variable_length(&self) -> bool; @@ -73,11 +73,9 @@ impl DCTypeDefinitionInterface for DCTypeDefinition { } /// Generates the hash for this DC Type element. - /// Method is prefixed with 'dctype_' to avoid collisions - /// with fake 'child' structs, that 'inherit' DC Type via - /// overriding the default Deref/DerefMut traits. - fn dctype_generate_hash(&self, hashgen: &mut DCHashGenerator) { + fn generate_hash(&self, hashgen: &mut DCHashGenerator) { hashgen.add_int(u32::from(self.data_type.clone() as u8)); + if self.alias.is_some() { hashgen.add_string(self.alias.clone().unwrap()) }