blob: 81b3124d34cc6cecf580f5145a69a05f8fadc0a1 [file] [log] [blame]
#include "src/lib/privacy/private_index_decoding.h"
#include "src/algorithms/privacy/numeric_encoding.h"
#include "src/logger/event_vector_index.h"
#include "src/public/lib/statusor/statusor.h"
namespace cobalt {
namespace {
Status ValidateIndexAsNumericValue(uint64_t index, uint64_t num_index_points) {
if (index >= num_index_points) {
return Status(StatusCode::INVALID_ARGUMENT,
"index is greater than or equal to num_index_points.");
}
return Status::OkStatus();
}
Status ValidateIndexAsCount(uint64_t index, uint64_t num_index_points) {
if (index < num_index_points) {
return Status(StatusCode::INVALID_ARGUMENT, "index is less than num_index_points.");
}
if (index >= 2 * num_index_points) {
return Status(StatusCode::INVALID_ARGUMENT,
"index is greater than or equal to 2 * num_index_points.");
}
return Status::OkStatus();
}
Status ValidateIndexAsHistogramBucketIndex(uint32_t index, uint32_t max_bucket_index) {
if (index > max_bucket_index) {
return Status(StatusCode::INVALID_ARGUMENT, "index is greater than the maximum bucket index.");
}
return Status::OkStatus();
}
} // namespace
Status DecodePrivateIndexAsEventVector(
uint64_t index,
const google::protobuf::RepeatedPtrField<MetricDefinition::MetricDimension>& metric_dimensions,
std::vector<uint32_t>* event_vector) {
lib::statusor::StatusOr<std::vector<uint32_t>> decoded_event_vector =
logger::EventVectorFromIndex(index, metric_dimensions);
if (decoded_event_vector.ok()) {
*event_vector = decoded_event_vector.ValueOrDie();
return Status::OkStatus();
}
return decoded_event_vector.status();
}
Status DecodePrivateIndexAsInteger(
uint64_t index,
const google::protobuf::RepeatedPtrField<MetricDefinition::MetricDimension>& metric_dimensions,
int64_t min_value, int64_t max_value, uint64_t num_index_points,
std::vector<uint32_t>* event_vector, int64_t* integer_value) {
double double_value = 0;
if (Status decode_as_double =
DecodePrivateIndexAsDouble(index, metric_dimensions, min_value, max_value,
num_index_points, event_vector, &double_value);
!decode_as_double.ok()) {
return decode_as_double;
}
*integer_value = static_cast<int64_t>(double_value);
return Status::OkStatus();
}
Status DecodePrivateIndexAsDouble(
uint64_t index,
const google::protobuf::RepeatedPtrField<MetricDefinition::MetricDimension>& metric_dimensions,
int64_t min_value, int64_t max_value, uint64_t num_index_points,
std::vector<uint32_t>* event_vector, double* double_value) {
uint64_t event_vector_index = 0;
uint64_t value_index = 0;
ValueAndEventVectorIndicesFromIndex(index, logger::GetNumEventVectors(metric_dimensions) - 1,
&value_index, &event_vector_index);
if (Status decode_event_vector_index =
DecodePrivateIndexAsEventVector(event_vector_index, metric_dimensions, event_vector);
!decode_event_vector_index.ok()) {
return decode_event_vector_index;
}
if (Status validate_value_index = ValidateIndexAsNumericValue(value_index, num_index_points);
!validate_value_index.ok()) {
return validate_value_index;
}
*double_value = DoubleFromIndex(value_index, static_cast<double>(min_value),
static_cast<double>(max_value), num_index_points);
return Status::OkStatus();
}
cobalt::Status DecodePrivateIndexAsSumOrCount(
uint64_t index,
const google::protobuf::RepeatedPtrField<MetricDefinition::MetricDimension>& metric_dimensions,
// TODO(fxbug.dev/85571): NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
int64_t min_value, int64_t max_value, uint64_t max_count, uint64_t num_index_points,
std::vector<uint32_t>* event_vector, SumOrCount* sum_or_count) {
uint64_t event_vector_index = 0;
uint64_t value_index = 0;
ValueAndEventVectorIndicesFromIndex(index, logger::GetNumEventVectors(metric_dimensions) - 1,
&value_index, &event_vector_index);
if (Status decode_event_vector_index =
DecodePrivateIndexAsEventVector(event_vector_index, metric_dimensions, event_vector);
!decode_event_vector_index.ok()) {
return decode_event_vector_index;
}
if (IsCountIndex(value_index, num_index_points)) {
if (Status validate_value_index = ValidateIndexAsCount(value_index, num_index_points);
!validate_value_index.ok()) {
return validate_value_index;
}
(*sum_or_count).type = SumOrCount::COUNT;
(*sum_or_count).count = CountFromIndex(value_index, max_count, num_index_points);
return Status::OkStatus();
}
if (Status validate_value_index = ValidateIndexAsNumericValue(value_index, num_index_points);
!validate_value_index.ok()) {
return validate_value_index;
}
(*sum_or_count).type = SumOrCount::SUM;
(*sum_or_count).sum = IntegerFromIndex(value_index, min_value, max_value, num_index_points);
return Status::OkStatus();
}
Status DecodePrivateIndexAsHistogramBucketIndex(
uint64_t index,
const google::protobuf::RepeatedPtrField<MetricDefinition::MetricDimension>& metric_dimensions,
uint32_t max_bucket_index, std::vector<uint32_t>* event_vector, uint32_t* bucket_index) {
uint64_t event_vector_index = 0;
uint64_t value_index = 0;
ValueAndEventVectorIndicesFromIndex(index, logger::GetNumEventVectors(metric_dimensions) - 1,
&value_index, &event_vector_index);
if (Status decode_event_vector_index =
DecodePrivateIndexAsEventVector(event_vector_index, metric_dimensions, event_vector);
!decode_event_vector_index.ok()) {
return decode_event_vector_index;
}
*bucket_index = static_cast<uint32_t>(value_index);
if (Status validate_bucket_index =
ValidateIndexAsHistogramBucketIndex(*bucket_index, max_bucket_index);
!validate_bucket_index.ok()) {
return validate_bucket_index;
}
return Status::OkStatus();
}
Status DecodePrivateIndexAsHistogramBucketIndexAndCount(
uint64_t index,
const google::protobuf::RepeatedPtrField<MetricDefinition::MetricDimension>& metric_dimensions,
// TODO(fxbug.dev/85571): NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
uint32_t max_bucket_index, uint64_t max_count, uint64_t num_index_points,
std::vector<uint32_t>* event_vector, uint32_t* bucket_index, uint64_t* bucket_count) {
uint64_t event_vector_index = 0;
uint64_t value_index = 0;
ValueAndEventVectorIndicesFromIndex(index, logger::GetNumEventVectors(metric_dimensions) - 1,
&value_index, &event_vector_index);
if (Status decode_event_vector_index =
DecodePrivateIndexAsEventVector(event_vector_index, metric_dimensions, event_vector);
!decode_event_vector_index.ok()) {
return decode_event_vector_index;
}
HistogramBucketAndCountFromIndex(value_index, max_count, num_index_points, bucket_index,
bucket_count);
if (Status validate_bucket_index =
ValidateIndexAsHistogramBucketIndex(*bucket_index, max_bucket_index);
!validate_bucket_index.ok()) {
return validate_bucket_index;
}
return Status::OkStatus();
}
} // namespace cobalt