This is an automated email from the ASF dual-hosted git repository.
tisonkun pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datasketches-rust.git
The following commit(s) were added to refs/heads/main by this push:
new f3df4b4 refactor(req): consolidate fallible constructors (#223)
f3df4b4 is described below
commit f3df4b4e9e44a8ee4792bacbfec88979500578e7
Author: Xuanwo <[email protected]>
AuthorDate: Fri Aug 28 14:49:37 2026 +0800
refactor(req): consolidate fallible constructors (#223)
Co-authored-by: tison <[email protected]>
---
datasketches/src/req/compactor.rs | 2 +-
datasketches/src/req/mod.rs | 17 +-
datasketches/src/req/sketch.rs | 205 +++++++--------------
datasketches/src/req/sorted_view.rs | 4 +-
datasketches/src/req/union.rs | 27 ++-
datasketches/src/tdigest/sketch.rs | 1 -
tests-integration/tests/req_test/accuracy.rs | 2 +-
tests-integration/tests/req_test/bounds.rs | 21 +--
tests-integration/tests/req_test/core.rs | 48 +++--
tests-integration/tests/req_test/merge.rs | 35 +---
tests-integration/tests/req_test/property.rs | 6 +-
tests-integration/tests/req_test/query.rs | 12 +-
.../tests/req_test/sorted_view_api.rs | 8 +-
tests-integration/tests/req_test/structure.rs | 8 +-
tests-integration/tests/req_test/union.rs | 24 +--
tests-integration/tests/serde_tests/req.rs | 11 +-
16 files changed, 165 insertions(+), 266 deletions(-)
diff --git a/datasketches/src/req/compactor.rs
b/datasketches/src/req/compactor.rs
index f614eec..da79181 100644
--- a/datasketches/src/req/compactor.rs
+++ b/datasketches/src/req/compactor.rs
@@ -480,7 +480,7 @@ where
items,
is_sorted,
state,
- scratch_buffer: Vec::new(),
+ scratch_buffer: vec![],
section_size: nearest_even_section_size(section_size_raw),
num_sections,
lg_weight,
diff --git a/datasketches/src/req/mod.rs b/datasketches/src/req/mod.rs
index a2b58f1..77e3698 100644
--- a/datasketches/src/req/mod.rs
+++ b/datasketches/src/req/mod.rs
@@ -31,17 +31,8 @@ mod sorted_view;
mod union;
mod value;
-/// Number of sections in a newly created compactor. The section count and size
-/// determine its capacity and compaction range; the count doubles as its
state grows.
-const INITIAL_SECTIONS_PER_COMPACTOR: u8 = 3;
-
-fn nearest_even_section_size(value: f32) -> u32 {
- ((value / 2.0).round() as u32) << 1
-}
-
pub use self::iter::ReqSketchIterator;
pub use self::sketch::ReqSketch;
-pub use self::sketch::ReqSketchBuilder;
pub use self::sorted_view::SortedView;
pub use self::union::ReqUnion;
pub use self::value::ReqValue;
@@ -72,3 +63,11 @@ pub enum SearchCriteria {
/// Exclude the weight of the search item from the result.
Exclusive,
}
+
+/// Number of sections in a newly created compactor. The section count and size
+/// determine its capacity and compaction range; the count doubles as its
state grows.
+const INITIAL_SECTIONS_PER_COMPACTOR: u8 = 3;
+
+fn nearest_even_section_size(value: f32) -> u32 {
+ ((value / 2.0).round() as u32) << 1
+}
diff --git a/datasketches/src/req/sketch.rs b/datasketches/src/req/sketch.rs
index d3a6cc3..61d8a91 100644
--- a/datasketches/src/req/sketch.rs
+++ b/datasketches/src/req/sketch.rs
@@ -17,8 +17,6 @@
//! REQ sketch — generic over `T: ReqValue`.
-use std::fmt;
-
use crate::codec::SketchBytes;
use crate::codec::SketchSlice;
use crate::codec::assert::insufficient_data;
@@ -50,71 +48,52 @@ use crate::req::value::ReqValue;
/// See the [module-level documentation](super) for background.
#[derive(Debug, Clone)]
pub struct ReqSketch<T: ReqValue> {
- pub(super) k: u16,
- pub(super) rank_accuracy: RankAccuracy,
- pub(super) n: u64,
- pub(super) max_nom_size: u32,
- pub(super) num_retained: u32,
- pub(super) compactors: Vec<Compactor<T>>,
- pub(super) promotion_buf: Vec<T>,
- pub(super) min_item: Option<T>,
- pub(super) max_item: Option<T>,
+ k: u16,
+ rank_accuracy: RankAccuracy,
+ n: u64,
+ max_nom_size: u32,
+ num_retained: u32,
+ compactors: Vec<Compactor<T>>,
+ promotion_buf: Vec<T>,
+ min_item: Option<T>,
+ max_item: Option<T>,
+}
+
+impl<T: ReqValue> Default for ReqSketch<T> {
+ fn default() -> Self {
+ Self::new(DEFAULT_K, RankAccuracy::HighRank)
+ }
}
impl<T: ReqValue> ReqSketch<T> {
- /// Creates a new sketch with default parameters (`k = 12`,
`RankAccuracy::HighRank`).
- pub fn new() -> Self {
- let mut s = Self {
- k: DEFAULT_K,
- rank_accuracy: RankAccuracy::HighRank,
- n: 0,
- max_nom_size: 0,
- num_retained: 0,
- compactors: Vec::new(),
- promotion_buf: Vec::with_capacity(DEFAULT_K as usize),
- min_item: None,
- max_item: None,
- };
- // C++ parity: an empty sketch has a level-0 compactor present from
the start.
- // This makes is_raw_items() and flags_byte() byte-compatible with the
C++/Java
- // wire format for the empty case.
- s.grow();
- s
+ /// Creates a new sketch with the given `k` and rank accuracy.
+ ///
+ /// The fallible version of this method is [`ReqSketch::try_new`].
+ ///
+ /// # Panics
+ ///
+ /// Panics if `k` is odd or outside `[4, 1024]`.
+ pub fn new(k: u16, rank_accuracy: RankAccuracy) -> Self {
+ Self::make(k, rank_accuracy)
}
/// Creates a new sketch with the given `k` and rank accuracy.
///
+ /// The panicking version of this method is [`ReqSketch::new`].
+ ///
/// # Errors
///
- /// Returns an error if `k` is odd or outside `[MIN_K, MAX_K]`.
+ /// Returns an error if `k` is odd or outside `[4, 1024]`.
pub fn try_new(k: u16, rank_accuracy: RankAccuracy) -> Result<Self, Error>
{
if !(MIN_K..=MAX_K).contains(&k) {
return Err(Error::invalid_argument(format!(
- "k must be in [{}, {}], got {k}",
- MIN_K, MAX_K
+ "k must be in [{MIN_K}, {MAX_K}], got {k}"
)));
}
if k % 2 != 0 {
return Err(Error::invalid_argument(format!("k must be even, got
{k}")));
}
- let mut s = Self {
- k,
- rank_accuracy,
- n: 0,
- max_nom_size: 0,
- num_retained: 0,
- compactors: Vec::new(),
- promotion_buf: Vec::with_capacity(k as usize),
- min_item: None,
- max_item: None,
- };
- s.grow();
- Ok(s)
- }
-
- /// Returns a builder for chained configuration.
- pub fn builder() -> ReqSketchBuilder<T> {
- ReqSketchBuilder::new()
+ Ok(Self::make(k, rank_accuracy))
}
/// Returns the configured `k` parameter.
@@ -600,8 +579,14 @@ impl<T: ReqValue> ReqSketch<T> {
} else {
RankAccuracy::LowRank
};
- if !(MIN_K..=MAX_K).contains(&k) || k % 2 != 0 {
- return Err(Error::deserial(format!("k {k} is not a valid REQ k
value")));
+
+ if !(MIN_K..=MAX_K).contains(&k) {
+ return Err(Error::deserial(format!(
+ "k must be in [{MIN_K}, {MAX_K}], got {k}"
+ )));
+ }
+ if k % 2 != 0 {
+ return Err(Error::deserial(format!("k must be even, got {k}")));
}
if is_empty {
@@ -615,7 +600,7 @@ impl<T: ReqValue> ReqSketch<T> {
"empty REQ sketch must have 0 raw items, got
{num_raw_items}"
)));
}
- return ReqSketch::try_new(k, rank_accuracy);
+ return Ok(Self::make(k, rank_accuracy));
}
if num_levels == 0 {
@@ -738,8 +723,7 @@ impl<T: ReqValue> ReqSketch<T> {
"REQ retained weighted count {weighted_count} does not match n
{n}"
)));
}
-
- let mut sketch = ReqSketch::try_new(k, rank_accuracy)?;
+ let mut sketch = Self::make(k, rank_accuracy);
sketch.n = n;
sketch.min_item = min_item;
sketch.max_item = max_item;
@@ -749,16 +733,39 @@ impl<T: ReqValue> ReqSketch<T> {
Ok(sketch)
}
- // --- Internal ---
+ fn make(k: u16, rank_accuracy: RankAccuracy) -> Self {
+ assert!(
+ (MIN_K..=MAX_K).contains(&k),
+ "k must be in [{MIN_K}, {MAX_K}], got {k}"
+ );
+ assert_eq!(k % 2, 0, "k must be even, got {k}");
- pub(super) fn grow(&mut self) {
+ let mut sketch = Self {
+ k,
+ rank_accuracy,
+ n: 0,
+ max_nom_size: 0,
+ num_retained: 0,
+ compactors: vec![],
+ promotion_buf: Vec::with_capacity(k as usize),
+ min_item: None,
+ max_item: None,
+ };
+ // C++ parity: an empty sketch has a level-0 compactor present from
the start.
+ // This makes is_raw_items() and flags_byte() byte-compatible with the
C++/Java
+ // wire format for the empty case.
+ sketch.grow();
+ sketch
+ }
+
+ fn grow(&mut self) {
let level = self.compactors.len() as u8;
let compactor = Compactor::new(level, self.k, self.rank_accuracy);
self.compactors.push(compactor);
self.update_max_nom_size();
}
- pub(super) fn compress(&mut self) {
+ fn compress(&mut self) {
for h in 0..self.compactors.len() {
if self.compactors[h].num_items() >=
self.compactors[h].nominal_capacity() {
if h == 0 {
@@ -779,89 +786,11 @@ impl<T: ReqValue> ReqSketch<T> {
}
}
- pub(super) fn update_max_nom_size(&mut self) {
+ fn update_max_nom_size(&mut self) {
self.max_nom_size = self.compactors.iter().map(|c|
c.nominal_capacity()).sum();
}
- pub(super) fn update_num_retained(&mut self) {
+ fn update_num_retained(&mut self) {
self.num_retained = self.compactors.iter().map(|c|
c.num_items()).sum();
}
}
-
-impl<T: ReqValue> Default for ReqSketch<T> {
- fn default() -> Self {
- Self::new()
- }
-}
-
-/// Builder for [`ReqSketch`].
-#[derive(Debug, Clone)]
-pub struct ReqSketchBuilder<T: ReqValue> {
- k: u16,
- rank_accuracy: RankAccuracy,
- _marker: std::marker::PhantomData<T>,
-}
-
-impl<T: ReqValue> Default for ReqSketchBuilder<T> {
- fn default() -> Self {
- Self::new()
- }
-}
-
-impl<T: ReqValue> ReqSketchBuilder<T> {
- /// Creates a new builder with default parameters.
- pub fn new() -> Self {
- Self {
- k: DEFAULT_K,
- rank_accuracy: RankAccuracy::HighRank,
- _marker: std::marker::PhantomData,
- }
- }
-
- /// Sets the `k` parameter.
- ///
- /// # Errors
- ///
- /// Returns an error if `k` is odd or outside `[MIN_K, MAX_K]`.
- pub fn k(mut self, k: u16) -> Result<Self, Error> {
- if !(MIN_K..=MAX_K).contains(&k) {
- return Err(Error::invalid_argument(format!(
- "k must be in [{}, {}], got {k}",
- MIN_K, MAX_K
- )));
- }
- if k % 2 != 0 {
- return Err(Error::invalid_argument(format!("k must be even, got
{k}")));
- }
- self.k = k;
- Ok(self)
- }
-
- /// Sets the rank accuracy.
- pub fn rank_accuracy(mut self, rank_accuracy: RankAccuracy) -> Self {
- self.rank_accuracy = rank_accuracy;
- self
- }
-
- /// Builds the sketch.
- pub fn build(self) -> Result<ReqSketch<T>, Error> {
- ReqSketch::try_new(self.k, self.rank_accuracy)
- }
-}
-
-impl<T: ReqValue + fmt::Display> fmt::Display for ReqSketch<T> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- writeln!(f, "REQ Sketch Summary:")?;
- writeln!(f, " k : {}", self.k)?;
- writeln!(f, " rank accuracy : {:?}", self.rank_accuracy)?;
- writeln!(f, " n : {}", self.n)?;
- writeln!(f, " num retained : {}", self.num_retained)?;
- writeln!(f, " num levels : {}", self.compactors.len())?;
- writeln!(f, " estimation mode : {}", self.is_estimation_mode())?;
- if let (Some(min), Some(max)) = (&self.min_item, &self.max_item) {
- writeln!(f, " min item : {min}")?;
- writeln!(f, " max item : {max}")?;
- }
- Ok(())
- }
-}
diff --git a/datasketches/src/req/sorted_view.rs
b/datasketches/src/req/sorted_view.rs
index 06ddcc0..a8c1d98 100644
--- a/datasketches/src/req/sorted_view.rs
+++ b/datasketches/src/req/sorted_view.rs
@@ -53,8 +53,8 @@ where
pub(super) fn new(mut weighted_items: Vec<(T, u64)>) -> Self {
if weighted_items.is_empty() {
return Self {
- items: Vec::new(),
- cumulative_weights: Vec::new(),
+ items: vec![],
+ cumulative_weights: vec![],
total_weight: 0,
};
}
diff --git a/datasketches/src/req/union.rs b/datasketches/src/req/union.rs
index 4ce49ae..ef9d001 100644
--- a/datasketches/src/req/union.rs
+++ b/datasketches/src/req/union.rs
@@ -18,6 +18,7 @@
//! REQ union — combines REQ sketches into a single result.
use crate::error::Error;
+use crate::req::DEFAULT_K;
use crate::req::RankAccuracy;
use crate::req::sketch::ReqSketch;
use crate::req::value::ReqValue;
@@ -30,16 +31,30 @@ pub struct ReqUnion<T: ReqValue> {
inner: ReqSketch<T>,
}
+impl<T: ReqValue> Default for ReqUnion<T> {
+ fn default() -> Self {
+ Self::new(DEFAULT_K, RankAccuracy::HighRank)
+ }
+}
+
impl<T: ReqValue> ReqUnion<T> {
- /// Creates a new union with default `k = 12` and `RankAccuracy::HighRank`.
- pub fn new() -> Self {
+ /// Creates a new union with the given `k` and rank accuracy.
+ ///
+ /// The fallible version of this method is [`ReqUnion::try_new`].
+ ///
+ /// # Panics
+ ///
+ /// Panics if `k` is invalid (see [`ReqSketch::new`]).
+ pub fn new(k: u16, rank_accuracy: RankAccuracy) -> Self {
Self {
- inner: ReqSketch::new(),
+ inner: ReqSketch::new(k, rank_accuracy),
}
}
/// Creates a new union with the given `k` and rank accuracy.
///
+ /// The panicking version of this method is [`ReqUnion::new`].
+ ///
/// # Errors
///
/// Returns an error if `k` is invalid (see [`ReqSketch::try_new`]).
@@ -86,9 +101,3 @@ impl<T: ReqValue> ReqUnion<T> {
self.inner.reset();
}
}
-
-impl<T: ReqValue> Default for ReqUnion<T> {
- fn default() -> Self {
- Self::new()
- }
-}
diff --git a/datasketches/src/tdigest/sketch.rs
b/datasketches/src/tdigest/sketch.rs
index 9acb558..cfc4105 100644
--- a/datasketches/src/tdigest/sketch.rs
+++ b/datasketches/src/tdigest/sketch.rs
@@ -247,7 +247,6 @@ impl TDigestMut {
))
}
- // for deserialization
fn make(
k: u16,
reverse_merge: bool,
diff --git a/tests-integration/tests/req_test/accuracy.rs
b/tests-integration/tests/req_test/accuracy.rs
index d8dc10b..8ca9fde 100644
--- a/tests-integration/tests/req_test/accuracy.rs
+++ b/tests-integration/tests/req_test/accuracy.rs
@@ -25,7 +25,7 @@ use googletest::prelude::le;
#[test]
fn rank_space_error_is_bounded() -> Result<(), Error> {
- let mut sketch = ReqSketch::new();
+ let mut sketch = ReqSketch::default();
let n = 50_000;
for i in 0..n {
diff --git a/tests-integration/tests/req_test/bounds.rs
b/tests-integration/tests/req_test/bounds.rs
index 6f18aa4..ced8d01 100644
--- a/tests-integration/tests/req_test/bounds.rs
+++ b/tests-integration/tests/req_test/bounds.rs
@@ -29,12 +29,7 @@ use googletest::prelude::lt;
#[test]
fn bounds_are_nested_and_in_unit_interval() {
- let mut sketch = ReqSketch::builder()
- .k(12)
- .expect("valid k")
- .rank_accuracy(RankAccuracy::HighRank)
- .build()
- .expect("build should succeed");
+ let mut sketch = ReqSketch::new(12, RankAccuracy::HighRank);
for i in 0..50_000 {
sketch.update(i as f64);
@@ -65,7 +60,7 @@ fn bounds_are_nested_and_in_unit_interval() {
#[test]
fn theoretical_error_bounds_cover_uniform_quantiles() -> Result<(), Error> {
- let mut sketch = ReqSketch::new();
+ let mut sketch = ReqSketch::default();
let n = 50_000;
for i in 0..n {
@@ -89,12 +84,8 @@ fn theoretical_error_bounds_cover_uniform_quantiles() ->
Result<(), Error> {
#[test]
fn hra_and_lra_bounds_are_tighter_at_their_target_end() -> Result<(), Error> {
for rank in [0.05, 0.25, 0.5, 0.75, 0.95] {
- let mut hra = ReqSketch::builder()
- .rank_accuracy(RankAccuracy::HighRank)
- .build()?;
- let mut lra = ReqSketch::builder()
- .rank_accuracy(RankAccuracy::LowRank)
- .build()?;
+ let mut hra = ReqSketch::new(12, RankAccuracy::HighRank);
+ let mut lra = ReqSketch::new(12, RankAccuracy::LowRank);
for i in 0..10_000 {
hra.update(i as f64);
@@ -118,7 +109,7 @@ fn hra_and_lra_bounds_are_tighter_at_their_target_end() ->
Result<(), Error> {
#[test]
fn exact_mode_bounds_are_tight() {
- let mut sketch = ReqSketch::new();
+ let mut sketch = ReqSketch::default();
for i in 0..20 {
sketch.update(i as f64);
@@ -135,7 +126,7 @@ fn exact_mode_bounds_are_tight() {
#[test]
fn high_rank_accuracy_matches_tight_thresholds() {
- let mut sketch = ReqSketch::new();
+ let mut sketch = ReqSketch::default();
let n = 50_000;
for i in 0..n {
diff --git a/tests-integration/tests/req_test/core.rs
b/tests-integration/tests/req_test/core.rs
index c46b44f..8e5804c 100644
--- a/tests-integration/tests/req_test/core.rs
+++ b/tests-integration/tests/req_test/core.rs
@@ -18,6 +18,8 @@
//! Core ReqSketch construction and update behavior.
use datasketches::error::Error;
+use datasketches::error::ErrorKind;
+use datasketches::req::DEFAULT_K;
use datasketches::req::RankAccuracy;
use datasketches::req::ReqSketch;
use datasketches::req::SearchCriteria;
@@ -31,11 +33,10 @@ use googletest::prelude::le;
use googletest::prelude::lt;
use googletest::prelude::near;
use googletest::prelude::none;
-use googletest::prelude::ok;
#[test]
fn empty_sketch_has_default_state_and_rejects_queries() {
- let sketch: ReqSketch<f32> = ReqSketch::new();
+ let sketch: ReqSketch<f32> = ReqSketch::default();
assert_eq!(sketch.k(), 12);
assert!(sketch.is_empty());
@@ -65,7 +66,7 @@ fn empty_sketch_has_default_state_and_rejects_queries() {
#[test]
fn single_value_hra_answers_exactly() {
- let mut sketch = ReqSketch::new();
+ let mut sketch = ReqSketch::default();
sketch.update(1.0f32);
assert!(!sketch.is_empty());
@@ -112,10 +113,7 @@ fn single_value_hra_answers_exactly() {
#[test]
fn single_value_lra_preserves_configuration() {
- let mut sketch: ReqSketch<f32> = ReqSketch::builder()
- .rank_accuracy(RankAccuracy::LowRank)
- .build()
- .expect("build should succeed");
+ let mut sketch = ReqSketch::<f32>::new(DEFAULT_K, RankAccuracy::LowRank);
sketch.update(1.0f32);
assert_eq!(sketch.rank_accuracy(), RankAccuracy::LowRank);
@@ -127,7 +125,7 @@ fn single_value_lra_preserves_configuration() {
#[test]
fn repeated_values_respect_search_criteria() {
- let mut sketch = ReqSketch::new();
+ let mut sketch = ReqSketch::default();
for _ in 0..3 {
sketch.update(1.0f32);
}
@@ -167,7 +165,7 @@ fn repeated_values_respect_search_criteria() {
#[test]
fn estimation_mode_compresses_and_keeps_min_max() {
- let mut sketch = ReqSketch::new();
+ let mut sketch = ReqSketch::default();
let n = 100_000;
for i in 0..n {
@@ -198,7 +196,7 @@ fn estimation_mode_compresses_and_keeps_min_max() {
#[test]
fn nan_updates_are_silently_skipped_for_f64() {
- let mut sketch: ReqSketch<f64> = ReqSketch::new();
+ let mut sketch: ReqSketch<f64> = ReqSketch::default();
sketch.update(f64::NAN);
sketch.update(f64::NAN);
assert!(sketch.is_empty());
@@ -214,7 +212,7 @@ fn nan_updates_are_silently_skipped_for_f64() {
#[test]
fn nan_updates_are_silently_skipped_for_f32() {
- let mut sketch: ReqSketch<f32> = ReqSketch::new();
+ let mut sketch: ReqSketch<f32> = ReqSketch::default();
sketch.update(f32::NAN);
assert!(sketch.is_empty());
assert_eq!(sketch.n(), 0);
@@ -232,17 +230,17 @@ fn nan_updates_are_silently_skipped_for_f32() {
#[test]
fn small_edge_cases_answer_reasonably() -> Result<(), Error> {
- let mut single = ReqSketch::new();
+ let mut single = ReqSketch::default();
single.update(42.0);
assert_eq!(single.quantile(0.5, SearchCriteria::Inclusive)?, 42.0);
- let mut two_values = ReqSketch::new();
+ let mut two_values = ReqSketch::default();
two_values.update(1.0);
two_values.update(100.0);
let median = two_values.quantile(0.5, SearchCriteria::Inclusive)?;
assert_that!(median, all!(ge(1.0), le(100.0)));
- let mut duplicates = ReqSketch::new();
+ let mut duplicates = ReqSketch::default();
for _ in 0..100 {
duplicates.update(42.0);
}
@@ -252,24 +250,22 @@ fn small_edge_cases_answer_reasonably() -> Result<(),
Error> {
}
#[test]
-fn constructors_validate_k() {
- // k must be even and within the supported range; both constructors
enforce it.
+fn try_new_validates_k() {
assert_that!(
ReqSketch::<f64>::try_new(0, RankAccuracy::HighRank),
err(anything())
);
- assert_that!(
- ReqSketch::<f64>::try_new(3, RankAccuracy::HighRank),
- err(anything())
- ); // odd
+ let error = ReqSketch::<f64>::try_new(3,
RankAccuracy::HighRank).unwrap_err();
+ assert_eq!(error.kind(), ErrorKind::InvalidArgument);
assert_that!(
ReqSketch::<f64>::try_new(4096, RankAccuracy::HighRank),
err(anything())
- ); // too large
- assert_that!(
- ReqSketch::<f64>::try_new(12, RankAccuracy::HighRank),
- ok(anything())
);
- assert_that!(ReqSketch::<f64>::builder().k(5), err(anything())); // odd
via builder
- assert_that!(ReqSketch::<f64>::builder().k(12), ok(anything()));
+ assert!(ReqSketch::<f64>::try_new(12, RankAccuracy::HighRank).is_ok());
+}
+
+#[test]
+#[should_panic(expected = "k must be even")]
+fn new_panics_on_invalid_k() {
+ let _ = ReqSketch::<f64>::new(5, RankAccuracy::HighRank);
}
diff --git a/tests-integration/tests/req_test/merge.rs
b/tests-integration/tests/req_test/merge.rs
index 1ab1c9e..d4123bf 100644
--- a/tests-integration/tests/req_test/merge.rs
+++ b/tests-integration/tests/req_test/merge.rs
@@ -27,16 +27,8 @@ use googletest::prelude::near;
#[test]
fn merge_into_empty_preserves_source_distribution() {
- let mut target: ReqSketch<f32> = ReqSketch::builder()
- .k(40)
- .expect("valid k")
- .build()
- .expect("build should succeed");
- let mut source: ReqSketch<f32> = ReqSketch::builder()
- .k(40)
- .expect("valid k")
- .build()
- .expect("build should succeed");
+ let mut target: ReqSketch<f32> = ReqSketch::new(40,
RankAccuracy::HighRank);
+ let mut source: ReqSketch<f32> = ReqSketch::new(40,
RankAccuracy::HighRank);
for i in 0..1000 {
source.update(i as f32);
@@ -67,16 +59,8 @@ fn merge_into_empty_preserves_source_distribution() {
#[test]
fn merge_two_ranges_preserves_distribution() {
- let mut left: ReqSketch<f32> = ReqSketch::builder()
- .k(100)
- .expect("valid k")
- .build()
- .expect("build should succeed");
- let mut right: ReqSketch<f32> = ReqSketch::builder()
- .k(100)
- .expect("valid k")
- .build()
- .expect("build should succeed");
+ let mut left: ReqSketch<f32> = ReqSketch::new(100, RankAccuracy::HighRank);
+ let mut right: ReqSketch<f32> = ReqSketch::new(100,
RankAccuracy::HighRank);
for i in 0..1000 {
left.update(i as f32);
@@ -110,11 +94,8 @@ fn merge_two_ranges_preserves_distribution() {
#[test]
fn merge_rejects_incompatible_accuracy_modes() {
- let mut high_rank = ReqSketch::new();
- let low_rank: ReqSketch<f32> = ReqSketch::builder()
- .rank_accuracy(RankAccuracy::LowRank)
- .build()
- .expect("build should succeed");
+ let mut high_rank = ReqSketch::default();
+ let low_rank: ReqSketch<f32> = ReqSketch::new(12, RankAccuracy::LowRank);
high_rank.update(1.0);
assert_that!(high_rank.merge(&low_rank), err(anything()));
@@ -122,10 +103,10 @@ fn merge_rejects_incompatible_accuracy_modes() {
#[test]
fn many_small_merges_preserve_count_bounds_and_median() {
- let mut sketch = ReqSketch::new();
+ let mut sketch = ReqSketch::default();
for batch in 0..100 {
- let mut batch_sketch = ReqSketch::new();
+ let mut batch_sketch = ReqSketch::default();
for i in 0..100 {
batch_sketch.update((batch * 100 + i) as f64);
}
diff --git a/tests-integration/tests/req_test/property.rs
b/tests-integration/tests/req_test/property.rs
index cbaf130..b70952d 100644
--- a/tests-integration/tests/req_test/property.rs
+++ b/tests-integration/tests/req_test/property.rs
@@ -30,7 +30,7 @@ fn prop_quantile_rank_consistency() {
return TestResult::discard();
}
- let mut sketch = ReqSketch::new();
+ let mut sketch = ReqSketch::default();
for value in values {
sketch.update(value);
}
@@ -78,7 +78,7 @@ fn prop_sketch_bounds() {
return TestResult::discard();
}
- let mut sketch = ReqSketch::new();
+ let mut sketch = ReqSketch::default();
for value in &values {
sketch.update(*value);
}
@@ -119,7 +119,7 @@ fn prop_rank_monotonicity() {
return TestResult::discard();
}
- let mut sketch = ReqSketch::new();
+ let mut sketch = ReqSketch::default();
for value in values {
sketch.update(value);
}
diff --git a/tests-integration/tests/req_test/query.rs
b/tests-integration/tests/req_test/query.rs
index 38e9513..c07bff9 100644
--- a/tests-integration/tests/req_test/query.rs
+++ b/tests-integration/tests/req_test/query.rs
@@ -29,7 +29,7 @@ use googletest::prelude::near;
#[test]
fn exact_mode_rank_quantile_pmf_and_cdf_match_reference() {
- let mut sketch = ReqSketch::new();
+ let mut sketch = ReqSketch::default();
for i in 1..=10 {
sketch.update(i as f32);
}
@@ -94,7 +94,7 @@ fn exact_mode_rank_quantile_pmf_and_cdf_match_reference() {
#[test]
fn pmf_and_cdf_are_consistent() {
- let mut sketch = ReqSketch::new();
+ let mut sketch = ReqSketch::default();
for i in 0..1000 {
sketch.update(i as f64);
}
@@ -119,7 +119,7 @@ fn pmf_and_cdf_are_consistent() {
#[test]
fn rank_is_monotonic_and_bounded() {
- let mut sketch = ReqSketch::new();
+ let mut sketch = ReqSketch::default();
for i in 0..10_000 {
sketch.update(i as f64);
}
@@ -139,7 +139,7 @@ fn rank_is_monotonic_and_bounded() {
#[test]
fn quantiles_are_monotonic() -> Result<(), Error> {
- let mut sketch = ReqSketch::new();
+ let mut sketch = ReqSketch::default();
for i in 0..10_000 {
sketch.update(i as f64);
}
@@ -158,7 +158,7 @@ fn quantiles_are_monotonic() -> Result<(), Error> {
#[test]
fn rank_quantile_round_trip_is_consistent() -> Result<(), Error> {
- let mut sketch = ReqSketch::new();
+ let mut sketch = ReqSketch::default();
for i in 0..10_000 {
sketch.update(i as f64);
}
@@ -175,7 +175,7 @@ fn rank_quantile_round_trip_is_consistent() -> Result<(),
Error> {
#[test]
fn search_criteria_rank_consistency() -> Result<(), Error> {
- let mut sketch = ReqSketch::new();
+ let mut sketch = ReqSketch::default();
for i in 0..1000 {
sketch.update(i as f64);
}
diff --git a/tests-integration/tests/req_test/sorted_view_api.rs
b/tests-integration/tests/req_test/sorted_view_api.rs
index f6eff2b..b5ed000 100644
--- a/tests-integration/tests/req_test/sorted_view_api.rs
+++ b/tests-integration/tests/req_test/sorted_view_api.rs
@@ -33,7 +33,7 @@ use googletest::prelude::lt;
use googletest::prelude::near;
fn populated_sketch(n: u64) -> ReqSketch<f64> {
- let mut sketch = ReqSketch::new();
+ let mut sketch = ReqSketch::default();
for i in 0..n {
sketch.update(i as f64);
}
@@ -85,7 +85,7 @@ fn sorted_view_is_an_owned_snapshot() {
#[test]
fn sorted_view_on_empty_sketch_is_an_empty_view() {
- let sketch: ReqSketch<f64> = ReqSketch::new();
+ let sketch: ReqSketch<f64> = ReqSketch::default();
let view = sketch.sorted_view();
assert!(view.is_empty());
assert_eq!(view.len(), 0);
@@ -99,7 +99,7 @@ fn sorted_view_on_empty_sketch_is_an_empty_view() {
#[test]
fn empty_sketch_pmf_cdf_report_error() {
- let sketch: ReqSketch<f64> = ReqSketch::new();
+ let sketch: ReqSketch<f64> = ReqSketch::default();
assert_that!(
sketch.pmf(&[1.0], SearchCriteria::Inclusive),
err(anything())
@@ -136,7 +136,7 @@ fn nan_query_items_are_rejected() {
#[test]
fn error_precedence_empty_before_invalid_rank() {
// On an empty sketch the emptiness is reported before the out-of-range
rank.
- let empty: ReqSketch<f64> = ReqSketch::new();
+ let empty: ReqSketch<f64> = ReqSketch::default();
let empty_err = empty.quantile(2.0,
SearchCriteria::Inclusive).unwrap_err();
assert_that!(empty_err.message(), contains_substring("empty"));
diff --git a/tests-integration/tests/req_test/structure.rs
b/tests-integration/tests/req_test/structure.rs
index c5bd42d..cbe2838 100644
--- a/tests-integration/tests/req_test/structure.rs
+++ b/tests-integration/tests/req_test/structure.rs
@@ -28,7 +28,7 @@ use googletest::prelude::predicate;
#[test]
fn iterator_weights_sum_to_n_and_items_are_in_range() {
- let mut sketch = ReqSketch::new();
+ let mut sketch = ReqSketch::default();
for i in 0..1000 {
sketch.update(i as f64);
}
@@ -46,7 +46,7 @@ fn iterator_weights_sum_to_n_and_items_are_in_range() {
#[test]
fn small_sketch_iterator_reports_unit_weights() {
// Below the compaction threshold every retained item still has weight 1.
- let mut sketch = ReqSketch::new();
+ let mut sketch = ReqSketch::default();
for i in 0..10 {
sketch.update(i as f64);
}
@@ -59,7 +59,7 @@ fn small_sketch_iterator_reports_unit_weights() {
#[test]
fn empty_sketch_iterator_yields_nothing() {
- let sketch: ReqSketch<i32> = ReqSketch::new();
+ let sketch: ReqSketch<i32> = ReqSketch::default();
assert_eq!(sketch.iter().count(), 0);
}
@@ -67,7 +67,7 @@ fn empty_sketch_iterator_yields_nothing() {
fn compaction_promotes_surviving_items_to_higher_weights() {
// After enough updates to trigger compaction, surviving items are
promoted up a
// level at double weight, so the maximum item weight exceeds 1.
- let mut sketch = ReqSketch::new();
+ let mut sketch = ReqSketch::default();
for i in 0..100_000 {
sketch.update(i as f64);
}
diff --git a/tests-integration/tests/req_test/union.rs
b/tests-integration/tests/req_test/union.rs
index 79e337e..61cdaeb 100644
--- a/tests-integration/tests/req_test/union.rs
+++ b/tests-integration/tests/req_test/union.rs
@@ -25,12 +25,11 @@ use googletest::assert_that;
use googletest::prelude::anything;
use googletest::prelude::err;
use googletest::prelude::near;
-use googletest::prelude::ok;
#[test]
fn union_equivalent_to_chained_merge() {
let make = |range: std::ops::Range<u64>| -> ReqSketch<f64> {
- let mut sketch = ReqSketch::new();
+ let mut sketch = ReqSketch::default();
for i in range {
sketch.update(i as f64);
}
@@ -40,13 +39,13 @@ fn union_equivalent_to_chained_merge() {
let s2 = make(1000..2000);
let s3 = make(2000..3000);
- let mut union: ReqUnion<f64> = ReqUnion::new();
+ let mut union: ReqUnion<f64> = ReqUnion::default();
union.merge(&s1).expect("merge should succeed");
union.merge(&s2).expect("merge should succeed");
union.merge(&s3).expect("merge should succeed");
let union_result = union.to_sketch();
- let mut via_merge: ReqSketch<f64> = ReqSketch::new();
+ let mut via_merge: ReqSketch<f64> = ReqSketch::default();
via_merge.merge(&s1).expect("merge should succeed");
via_merge.merge(&s2).expect("merge should succeed");
via_merge.merge(&s3).expect("merge should succeed");
@@ -70,18 +69,18 @@ fn union_equivalent_to_chained_merge() {
#[test]
fn empty_union_returns_empty_sketch() {
- let union: ReqUnion<f64> = ReqUnion::new();
+ let union: ReqUnion<f64> = ReqUnion::default();
assert!(union.to_sketch().is_empty());
}
#[test]
fn reset_clears_union_state() {
- let mut sketch: ReqSketch<f64> = ReqSketch::new();
+ let mut sketch: ReqSketch<f64> = ReqSketch::default();
for i in 0..100 {
sketch.update(i as f64);
}
- let mut union: ReqUnion<f64> = ReqUnion::new();
+ let mut union: ReqUnion<f64> = ReqUnion::default();
union.merge(&sketch).expect("merge should succeed");
assert!(!union.is_empty());
@@ -95,15 +94,12 @@ fn try_new_validates_k() {
ReqUnion::<f64>::try_new(3, RankAccuracy::HighRank),
err(anything())
);
- assert_that!(
- ReqUnion::<f64>::try_new(12, RankAccuracy::HighRank),
- ok(anything())
- );
+ assert!(ReqUnion::<f64>::try_new(12, RankAccuracy::HighRank).is_ok());
}
#[test]
fn empty_union_uses_default_configuration() {
- let union: ReqUnion<f64> = ReqUnion::new();
+ let union: ReqUnion<f64> = ReqUnion::default();
assert_eq!(union.k(), 12);
assert_eq!(union.rank_accuracy(), RankAccuracy::HighRank);
}
@@ -111,12 +107,12 @@ fn empty_union_uses_default_configuration() {
#[test]
fn union_keeps_default_k_when_merging_mismatched_sketch() {
// The union retains its own k even when fed a sketch built with a
different k.
- let mut other = ReqSketch::<f64>::try_new(16,
RankAccuracy::HighRank).expect("valid k");
+ let mut other = ReqSketch::<f64>::new(16, RankAccuracy::HighRank);
for i in 0..50 {
other.update(i as f64);
}
- let mut union: ReqUnion<f64> = ReqUnion::new();
+ let mut union: ReqUnion<f64> = ReqUnion::default();
union.merge(&other).expect("merge should succeed");
let result = union.to_sketch();
diff --git a/tests-integration/tests/serde_tests/req.rs
b/tests-integration/tests/serde_tests/req.rs
index a5e48fa..7a38af5 100644
--- a/tests-integration/tests/serde_tests/req.rs
+++ b/tests-integration/tests/serde_tests/req.rs
@@ -184,19 +184,18 @@ fn deserialize_odd_k() {
11u8, 0u8, // k=11 (odd)
0u8, 0u8,
];
- let result = ReqSketch::<f32>::deserialize(&bytes);
- assert_that!(result, err(anything()));
+ assert_invalid_data(&bytes);
}
#[test]
fn deserialize_k_out_of_range() {
// k must be in [4, 1024]. Try k=2 (too small).
let bytes_small = [2u8, 1, 17, 4, 2, 0, 0, 0];
- assert_that!(ReqSketch::<f32>::deserialize(&bytes_small), err(anything()));
+ assert_invalid_data(&bytes_small);
// k=2048 (too large): little-endian 2048 = [0x00, 0x08]
let bytes_big = [2u8, 1, 17, 4, 0, 8, 0, 0];
- assert_that!(ReqSketch::<f32>::deserialize(&bytes_big), err(anything()));
+ assert_invalid_data(&bytes_big);
}
#[test]
@@ -233,8 +232,8 @@ fn deserialize_truncated_raw_items() {
#[test]
fn merge_preserves_order_across_serde_round_trip() {
- let mut high = ReqSketch::<f64>::new();
- let mut low = ReqSketch::<f64>::new();
+ let mut high = ReqSketch::<f64>::default();
+ let mut low = ReqSketch::<f64>::default();
for value in 1000..=1072 {
high.update(value as f64);
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]