ddsketch/canonical/store/
mod.rs

1//! Sketch storage.
2
3use datadog_protos::sketches::Store as ProtoStore;
4
5use super::error::ProtoConversionError;
6
7mod collapsing_highest;
8pub use self::collapsing_highest::CollapsingHighestDenseStore;
9
10mod collapsing_lowest;
11pub use self::collapsing_lowest::CollapsingLowestDenseStore;
12
13mod dense;
14pub use self::dense::DenseStore;
15
16mod sparse;
17pub use self::sparse::SparseStore;
18
19/// Storage for sketch observations.
20///
21/// Stores manage holding the counts of mapped values, such that they contain a list of bins and the number of
22/// observations currently counted in each bin.
23pub trait Store: Clone + Send + Sync {
24    /// Adds a count to the bin at the given index.
25    fn add(&mut self, index: i32, count: u64);
26
27    /// Returns the total count across all bins.
28    fn total_count(&self) -> u64;
29
30    /// Returns the minimum index with a non-zero count, or `None` if empty.
31    fn min_index(&self) -> Option<i32>;
32
33    /// Returns the maximum index with a non-zero count, or `None` if empty.
34    fn max_index(&self) -> Option<i32>;
35
36    /// Returns the index of the bin containing the given rank.
37    ///
38    /// The rank is 0-indexed, so rank 0 is the first observation.
39    fn key_at_rank(&self, rank: u64) -> Option<i32>;
40
41    /// Merges another store into this one.
42    fn merge(&mut self, other: &Self);
43
44    /// Returns `true` if the store is empty.
45    fn is_empty(&self) -> bool;
46
47    /// Clears all bins from the store.
48    fn clear(&mut self);
49
50    /// Populates this store from a protobuf `Store`.
51    fn merge_from_proto(&mut self, proto: &ProtoStore) -> Result<(), ProtoConversionError>;
52
53    /// Converts this store to a protobuf `Store`.
54    fn to_proto(&self) -> ProtoStore;
55}
56
57/// Validates and converts a protobuf `f64` count to `u64`.
58///
59/// # Errors
60///
61/// If the count is negative, or has a fractional part, an error is returned.
62pub(crate) fn validate_proto_count(index: i32, count: f64) -> Result<u64, ProtoConversionError> {
63    if count < 0.0 {
64        return Err(ProtoConversionError::NegativeBinCount { index, count });
65    }
66    if count.fract() != 0.0 {
67        return Err(ProtoConversionError::NonIntegerBinCount { index, count });
68    }
69    Ok(count as u64)
70}