From d5f3010f9df2fa9b0adc5f61fc2fc20cb5fdad6e Mon Sep 17 00:00:00 2001 From: Daan Steenbergen Date: Sat, 12 Aug 2023 22:52:29 +0200 Subject: [PATCH] feat(NAME)!: faster and conciser filtering for values --- src/network_management/name.rs | 249 ++++++++++++--------------------- 1 file changed, 87 insertions(+), 162 deletions(-) diff --git a/src/network_management/name.rs b/src/network_management/name.rs index ac62351..5818455 100644 --- a/src/network_management/name.rs +++ b/src/network_management/name.rs @@ -29,153 +29,59 @@ impl NAME { NameBuilder::default() } - pub fn check_mask(name_to_check: &NAME, name_fields: &Vec) -> bool { - let mut matched = false; - if (!name_fields.is_empty()) && (&NAME::default() != name_to_check) { - matched = true; - - for field in name_fields { - if let NameField::IdentityNumber(value) = field { - if *value == name_to_check.get_identity_number() { - matched = true; - break; - } else { - matched = false; - } + pub fn has_field_value(&self, field_value: NameField) -> bool { + *self != NAME::default() + && match field_value { + NameField::IdentityNumber(value) => self.get_identity_number() == value, + NameField::ShortIdentityNumber(value) => self.get_short_identity_number() == value, + NameField::ExtendedIdentityNumber(value) => { + self.get_extended_identity_number() == value } - } - - if matched { - for field in name_fields { - if let NameField::ShortIdentityNumber(value) = field { - if *value == name_to_check.get_short_identity_number() { - matched = true; - break; - } else { - matched = false; - } - } - } - } - - if matched { - for field in name_fields { - if let NameField::ExtendedIdentityNumber(value) = field { - if *value == name_to_check.get_extended_identity_number() { - matched = true; - break; - } else { - matched = false; - } - } - } - } - - if matched { - for field in name_fields { - if let NameField::ManufacturerCode(value) = field { - if *value == name_to_check.get_manufacturer_code() { - matched = true; - break; - } else { - matched = false; - } - } - } - } - - if matched { - for field in name_fields { - if let NameField::EcuInstance(value) = field { - if *value == name_to_check.get_ecu_instance() { - matched = true; - break; - } else { - matched = false; - } - } - } - } - - if matched { - for field in name_fields { - if let NameField::FunctionInstance(value) = field { - if *value == name_to_check.get_function_instance() { - matched = true; - break; - } else { - matched = false; - } - } - } - } - - if matched { - for field in name_fields { - if let NameField::Function(value) = field { - if *value == name_to_check.get_function() { - matched = true; - break; - } else { - matched = false; - } - } - } - } - - if matched { - for field in name_fields { - if let NameField::DeviceClass(value) = field { - if *value == name_to_check.get_device_class() { - matched = true; - break; - } else { - matched = false; - } - } - } - } - - if matched { - for field in name_fields { - if let NameField::DeviceClassInstance(value) = field { - if *value == name_to_check.get_device_class_instance() { - matched = true; - break; - } else { - matched = false; - } - } + NameField::ManufacturerCode(value) => self.get_manufacturer_code() == value, + NameField::EcuInstance(value) => self.get_ecu_instance() == value, + NameField::FunctionInstance(value) => self.get_function_instance() == value, + NameField::Function(value) => self.get_function() == value, + NameField::DeviceClass(value) => self.get_device_class() == value, + NameField::DeviceClassInstance(value) => self.get_device_class_instance() == value, + NameField::IndustryGroup(value) => self.get_industry_group() == value, + NameField::SelfConfigurableAddress(value) => { + self.get_self_configurable_address() == value } } + } - if matched { - for field in name_fields { - if let NameField::IndustryGroup(value) = field { - if *value == name_to_check.get_industry_group() { - matched = true; - break; - } else { - matched = false; - } - } - } + pub fn has_field_values(&self, name_fields: &[NameField]) -> bool { + /// A helper function to get the index of a field + /// This is used to set the bits in a mask to check if all supplied fields are satisfied + fn get_index(field: &NameField) -> u8 { + match field { + NameField::IdentityNumber(_) => 0, + NameField::ShortIdentityNumber(_) => 1, + NameField::ExtendedIdentityNumber(_) => 2, + NameField::ManufacturerCode(_) => 3, + NameField::EcuInstance(_) => 4, + NameField::FunctionInstance(_) => 5, + NameField::Function(_) => 6, + NameField::DeviceClass(_) => 7, + NameField::DeviceClassInstance(_) => 8, + NameField::IndustryGroup(_) => 9, + NameField::SelfConfigurableAddress(_) => 10, } + } - if matched { - for field in name_fields { - if let NameField::SelfConfigurableAddress(value) = field { - if *value == name_to_check.get_self_configurable_address() { - matched = true; - break; - } else { - matched = false; - } - } - } + // Make a mask of all the fields present in the supplied array + let fields_present = name_fields.iter().fold(0_u16, |acc, name_field| { + return acc | 1 << get_index(name_field); + }); + // Make a mask of all the fields satisfied in the supplied array + let fields_satisfied = name_fields.iter().fold(0_u16, |acc, name_field| { + if self.has_field_value(*name_field) { + return acc | 1 << get_index(name_field); + } else { + return acc; } - } - return matched; + }); + return fields_satisfied == fields_present; } pub fn get_device_class(&self) -> u8 { @@ -463,67 +369,86 @@ mod tests { fn test_filter_matching() { let mut test_name = NAME::new(0); let mut filters_to_test = Vec::new(); + let identity_number_filter = NameField::IdentityNumber(1); filters_to_test.push(identity_number_filter); + assert_eq!(false, test_name.has_field_value(identity_number_filter)); + assert_eq!(false, test_name.has_field_values(&filters_to_test)); - assert_eq!(false, NAME::check_mask(&test_name, &filters_to_test)); test_name.set_identity_number(1); - assert_eq!(true, NAME::check_mask(&test_name, &filters_to_test)); + assert_eq!(true, test_name.has_field_value(identity_number_filter)); + assert_eq!(true, test_name.has_field_values(&filters_to_test)); let manufacturer_number_filter = NameField::ManufacturerCode(2); filters_to_test.push(manufacturer_number_filter); + assert_eq!(false, test_name.has_field_value(manufacturer_number_filter)); + assert_eq!(false, test_name.has_field_values(&filters_to_test)); - assert_eq!(false, NAME::check_mask(&test_name, &filters_to_test)); test_name.set_manufacturer_code(2); - assert_eq!(true, NAME::check_mask(&test_name, &filters_to_test)); + assert_eq!(true, test_name.has_field_value(manufacturer_number_filter)); + assert_eq!(true, test_name.has_field_values(&filters_to_test)); let ecu_instance_filter = NameField::EcuInstance(3); filters_to_test.push(ecu_instance_filter); + assert_eq!(false, test_name.has_field_value(ecu_instance_filter)); + assert_eq!(false, test_name.has_field_values(&filters_to_test)); - assert_eq!(false, NAME::check_mask(&test_name, &filters_to_test)); test_name.set_ecu_instance(3); - assert_eq!(true, NAME::check_mask(&test_name, &filters_to_test)); + assert_eq!(true, test_name.has_field_value(ecu_instance_filter)); + assert_eq!(true, test_name.has_field_values(&filters_to_test)); let function_instance_filter = NameField::FunctionInstance(4); filters_to_test.push(function_instance_filter); + assert_eq!(false, test_name.has_field_value(function_instance_filter)); + assert_eq!(false, test_name.has_field_values(&filters_to_test)); - assert_eq!(false, NAME::check_mask(&test_name, &filters_to_test)); test_name.set_function_instance(4); - assert_eq!(true, NAME::check_mask(&test_name, &filters_to_test)); + assert_eq!(true, test_name.has_field_value(function_instance_filter)); + assert_eq!(true, test_name.has_field_values(&filters_to_test)); let function_filter = NameField::Function(5); filters_to_test.push(function_filter); + assert_eq!(false, test_name.has_field_value(function_filter)); + assert_eq!(false, test_name.has_field_values(&filters_to_test)); - assert_eq!(false, NAME::check_mask(&test_name, &filters_to_test)); test_name.set_function(5); - assert_eq!(true, NAME::check_mask(&test_name, &filters_to_test)); + assert_eq!(true, test_name.has_field_value(function_filter)); + assert_eq!(true, test_name.has_field_values(&filters_to_test)); let device_class_filter = NameField::DeviceClass(6); filters_to_test.push(device_class_filter); + assert_eq!(false, test_name.has_field_value(device_class_filter)); + assert_eq!(false, test_name.has_field_values(&filters_to_test)); - assert_eq!(false, NAME::check_mask(&test_name, &filters_to_test)); test_name.set_device_class(6); - assert_eq!(true, NAME::check_mask(&test_name, &filters_to_test)); + assert_eq!(true, test_name.has_field_value(device_class_filter)); + assert_eq!(true, test_name.has_field_values(&filters_to_test)); let industry_group_filter = NameField::IndustryGroup(7); filters_to_test.push(industry_group_filter); + assert_eq!(false, test_name.has_field_value(industry_group_filter)); + assert_eq!(false, test_name.has_field_values(&filters_to_test)); - assert_eq!(false, NAME::check_mask(&test_name, &filters_to_test)); test_name.set_industry_group(7); - assert_eq!(true, NAME::check_mask(&test_name, &filters_to_test)); + assert_eq!(true, test_name.has_field_value(industry_group_filter)); + assert_eq!(true, test_name.has_field_values(&filters_to_test)); - let device_class_instance_filter = NameField::DeviceClassInstance(8); - filters_to_test.push(device_class_instance_filter); + let device_class_inst_filter = NameField::DeviceClassInstance(8); + filters_to_test.push(device_class_inst_filter); + assert_eq!(false, test_name.has_field_value(device_class_inst_filter)); + assert_eq!(false, test_name.has_field_values(&filters_to_test)); - assert_eq!(false, NAME::check_mask(&test_name, &filters_to_test)); test_name.set_device_class_instance(8); - assert_eq!(true, NAME::check_mask(&test_name, &filters_to_test)); + assert_eq!(true, test_name.has_field_value(device_class_inst_filter)); + assert_eq!(true, test_name.has_field_values(&filters_to_test)); - let self_configurable_address_filter = NameField::SelfConfigurableAddress(true); - filters_to_test.push(self_configurable_address_filter); + let self_config_address_filter = NameField::SelfConfigurableAddress(true); + filters_to_test.push(self_config_address_filter); + assert_eq!(false, test_name.has_field_value(self_config_address_filter)); + assert_eq!(false, test_name.has_field_values(&filters_to_test)); - assert_eq!(false, NAME::check_mask(&test_name, &filters_to_test)); test_name.set_self_configurable_address(true); - assert_eq!(true, NAME::check_mask(&test_name, &filters_to_test)); + assert_eq!(true, test_name.has_field_value(self_config_address_filter)); + assert_eq!(true, test_name.has_field_values(&filters_to_test)); } }