use bacnet_types::constructed::{BACnetAuthenticationFactor, BACnetAuthenticationFactorFormat};
use bacnet_types::enums::AuthenticationFactorType;
use super::credential_data_input_out_of_service::Reading;
use super::UpdateClock;
pub(super) type SupportedFormat = (BACnetAuthenticationFactorFormat, u32);
pub(super) fn undefined_factor() -> BACnetAuthenticationFactor {
BACnetAuthenticationFactor {
format_type: AuthenticationFactorType::UNDEFINED,
format_class: 0,
value: Vec::new(),
}
}
pub(super) fn is_factor_type(format_type: AuthenticationFactorType) -> bool {
format_type.to_raw() <= AuthenticationFactorType::USER_PASSWORD.to_raw()
}
pub(super) fn is_well_formed(format: &BACnetAuthenticationFactorFormat) -> bool {
if !is_factor_type(format.format_type) {
return false;
}
if format.format_type == AuthenticationFactorType::CUSTOM {
format.vendor_id.is_some() && format.vendor_format.is_some()
} else {
format.vendor_id.unwrap_or(0) == 0 && format.vendor_format.unwrap_or(0) == 0
}
}
pub(super) fn is_declared(
factor: &BACnetAuthenticationFactor,
formats: &[SupportedFormat],
) -> bool {
if !is_factor_type(factor.format_type) {
return false;
}
if factor.format_type == AuthenticationFactorType::UNDEFINED {
return factor.format_class == 0;
}
formats.iter().any(|(format, class)| {
format.format_type == factor.format_type && *class == factor.format_class
}) || (factor.format_type == AuthenticationFactorType::ERROR && factor.format_class == 0)
}
pub(super) fn drop_undeclared(
reading: &mut Reading,
formats: &[SupportedFormat],
clock: &mut UpdateClock,
) {
if is_declared(&reading.present_value, formats) {
return;
}
reading.present_value = undefined_factor();
reading.update_time = clock.stamp();
}