use bacnet_objects::audit::AuditLogQueryPage;
use bacnet_objects::database::ObjectDatabase;
use bacnet_services::audit::AuditLogQueryRequest;
use bacnet_types::enums::{ErrorClass, ErrorCode, ObjectType};
use bacnet_types::error::Error;
use bacnet_types::primitives::ObjectIdentifier;
fn unknown_object() -> Error {
Error::protocol(ErrorClass::OBJECT, ErrorCode::UNKNOWN_OBJECT)
}
fn optional_functionality_not_supported() -> Error {
Error::protocol(
ErrorClass::SERVICES,
ErrorCode::OPTIONAL_FUNCTIONALITY_NOT_SUPPORTED,
)
}
pub fn handle_audit_log_query(
db: &ObjectDatabase,
service_data: &[u8],
) -> Result<(ObjectIdentifier, AuditLogQueryPage), Error> {
handle_audit_log_query_observed(db, service_data, |_, _| {})
}
pub(crate) fn handle_audit_log_query_observed(
db: &ObjectDatabase,
service_data: &[u8],
completed: impl FnOnce(ObjectIdentifier, &Result<AuditLogQueryPage, Error>),
) -> Result<(ObjectIdentifier, AuditLogQueryPage), Error> {
let request = AuditLogQueryRequest::decode(service_data).map_err(Error::into_request_reject)?;
let result = query(db, &request);
completed(request.audit_log, &result);
result.map(|page| (request.audit_log, page))
}
fn query(db: &ObjectDatabase, request: &AuditLogQueryRequest) -> Result<AuditLogQueryPage, Error> {
if request.audit_log.object_type() != ObjectType::AUDIT_LOG {
return Err(unknown_object());
}
let object = db.get(&request.audit_log).ok_or_else(unknown_object)?;
let storage = object
.audit_log_storage_internal()
.ok_or_else(optional_functionality_not_supported)?;
let page = storage.query(
&request.query_parameters,
request.start_at_sequence_number,
request.requested_count,
);
Ok(page)
}