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]

Reply via email to