From d81715670169fd925918fef8905e65b5cab630ff Mon Sep 17 00:00:00 2001 From: tison Date: Sat, 29 Aug 2026 16:02:05 +0800 Subject: [PATCH 1/2] refactor: align internal symbol visibility Let private module boundaries control shared implementation items, while retaining restricted visibility where re-exported public types or modules require it. Document the convention and remove same-module visibility drift. --- CONTRIBUTING.md | 6 ++ datasketches/src/codec/assert.rs | 8 +-- datasketches/src/common/inv_pow2.rs | 2 +- datasketches/src/countmin/serialization.rs | 8 +-- datasketches/src/cpc/compression.rs | 15 ++--- datasketches/src/cpc/compression_data.rs | 12 ++-- datasketches/src/cpc/estimator.rs | 6 +- datasketches/src/cpc/kxp_byte_lookup.rs | 2 +- datasketches/src/cpc/pair_table.rs | 2 +- datasketches/src/cpc/serialization.rs | 12 ++-- datasketches/src/cpc/sketch.rs | 2 +- .../reverse_purge_item_hash_map.rs | 2 +- datasketches/src/hash/seed.rs | 4 +- datasketches/src/hll/array4.rs | 12 ++-- datasketches/src/hll/array6.rs | 8 +-- datasketches/src/hll/array8.rs | 16 +++--- datasketches/src/hll/estimator.rs | 17 ++---- datasketches/src/req/compactor.rs | 57 +++++++------------ datasketches/src/req/serialization.rs | 22 +++---- datasketches/src/req/sketch.rs | 4 +- datasketches/src/tdigest/serialization.rs | 16 +++--- datasketches/src/tdigest/sketch.rs | 6 +- .../src/thetafamily/theta/bit_pack.rs | 10 ++-- .../src/thetafamily/theta/hash_table.rs | 2 +- .../src/thetafamily/theta/serialization.rs | 10 ++-- .../src/thetafamily/tuple/hash_table.rs | 2 +- .../src/thetafamily/tuple/serialization.rs | 8 +-- 27 files changed, 126 insertions(+), 145 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3812d38f..4ef490b8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -80,6 +80,12 @@ cargo bench --package benchmarks --bench benchmarks -- cpc::serde - End summary sentences with punctuation, and format Rust identifiers, literals, and numeric ranges as inline code. - Put contract sections and compatibility notes before examples. When applicable, order sections as `# Errors`, `# Panics`, and `# Examples`. Include only sections that describe an actual contract. +## Visibility + +- Let module visibility define the boundary for implementation items. Inside a private module, use `pub` when an item must be available outside its defining module. Inside a `pub(crate)` module, use `pub` when the item should be available wherever that module is visible. Do not repeat an enclosing restriction when it adds no narrower boundary. +- Keep items private when they are used only by their defining module and its descendants. +- For items reachable through a public module or a re-exported public type, use the narrowest visibility that supports their internal callers. Reserve unrestricted `pub` for intentional public API. + ## Changelog - Update `CHANGELOG.md` in the same pull request for significant user-visible changes. Compare the final behavior with the latest release tag rather than recording the sequence of commits that produced it. diff --git a/datasketches/src/codec/assert.rs b/datasketches/src/codec/assert.rs index 2ef5ee52..71d18ec7 100644 --- a/datasketches/src/codec/assert.rs +++ b/datasketches/src/codec/assert.rs @@ -20,11 +20,11 @@ use std::ops::RangeBounds; use crate::error::Error; -pub(crate) fn insufficient_data(tag: &'static str) -> impl FnOnce(std::io::Error) -> Error { +pub fn insufficient_data(tag: &'static str) -> impl FnOnce(std::io::Error) -> Error { move |_| Error::insufficient_data(tag) } -pub(crate) fn ensure_serial_version_is(expected: u8, actual: u8) -> Result<(), Error> { +pub fn ensure_serial_version_is(expected: u8, actual: u8) -> Result<(), Error> { if expected == actual { Ok(()) } else { @@ -34,7 +34,7 @@ pub(crate) fn ensure_serial_version_is(expected: u8, actual: u8) -> Result<(), E } } -pub(crate) fn ensure_preamble_longs_in(expected: &[u8], actual: u8) -> Result<(), Error> { +pub fn ensure_preamble_longs_in(expected: &[u8], actual: u8) -> Result<(), Error> { if expected.contains(&actual) { Ok(()) } else { @@ -42,7 +42,7 @@ pub(crate) fn ensure_preamble_longs_in(expected: &[u8], actual: u8) -> Result<() } } -pub(crate) fn ensure_preamble_longs_in_range( +pub fn ensure_preamble_longs_in_range( expected: impl RangeBounds, actual: u8, ) -> Result<(), Error> { diff --git a/datasketches/src/common/inv_pow2.rs b/datasketches/src/common/inv_pow2.rs index 353faa25..a61f1ca2 100644 --- a/datasketches/src/common/inv_pow2.rs +++ b/datasketches/src/common/inv_pow2.rs @@ -17,7 +17,7 @@ /// Compute 1 / 2^exp using the same bit construction as DataSketches Java. #[inline] -pub(crate) fn inv_pow2(exp: u8) -> f64 { +pub fn inv_pow2(exp: u8) -> f64 { f64::from_bits((1023 - exp as u64) << 52) } diff --git a/datasketches/src/countmin/serialization.rs b/datasketches/src/countmin/serialization.rs index 4f078a95..7a930e01 100644 --- a/datasketches/src/countmin/serialization.rs +++ b/datasketches/src/countmin/serialization.rs @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License. -pub(super) const PREAMBLE_LONGS_SHORT: u8 = 2; -pub(super) const SERIAL_VERSION: u8 = 1; -pub(super) const FLAGS_IS_EMPTY: u8 = 1 << 0; -pub(super) const LONG_SIZE_BYTES: usize = 8; +pub const PREAMBLE_LONGS_SHORT: u8 = 2; +pub const SERIAL_VERSION: u8 = 1; +pub const FLAGS_IS_EMPTY: u8 = 1 << 0; +pub const LONG_SIZE_BYTES: usize = 8; diff --git a/datasketches/src/cpc/compression.rs b/datasketches/src/cpc/compression.rs index 4cefe569..71b65ffd 100644 --- a/datasketches/src/cpc/compression.rs +++ b/datasketches/src/cpc/compression.rs @@ -24,7 +24,7 @@ use crate::cpc::compression_data::LENGTH_LIMITED_UNARY_DECODING_TABLE65; use crate::cpc::compression_data::LENGTH_LIMITED_UNARY_ENCODING_TABLE65; use crate::error::Error; -pub(super) fn encode_pairs(pairs: &[u32], lg_k: u8, output: &mut SketchBytes) -> usize { +pub fn encode_pairs(pairs: &[u32], lg_k: u8, output: &mut SketchBytes) -> usize { let num_pairs = pairs.len() as u32; let num_base_bits = golomb_choose_number_of_base_bits((1 << lg_k) + num_pairs, u64::from(num_pairs)); @@ -57,12 +57,7 @@ pub(super) fn encode_pairs(pairs: &[u32], lg_k: u8, output: &mut SketchBytes) -> bits.finish() } -pub(super) fn encode_window( - window: &[u8], - lg_k: u8, - num_coupons: u32, - output: &mut SketchBytes, -) -> usize { +pub fn encode_window(window: &[u8], lg_k: u8, num_coupons: u32, output: &mut SketchBytes) -> usize { let pseudo_phase = determine_pseudo_phase(lg_k, num_coupons); let encoding_table = &ENCODING_TABLES_FOR_HIGH_ENTROPY_BYTE[pseudo_phase as usize]; let mut bits = BitWriter::new(output); @@ -130,7 +125,7 @@ impl<'a> BitWriter<'a> { } } -pub(super) fn decode_pairs(data: &[u8], num_pairs: u32, lg_k: u8) -> Result, Error> { +pub fn decode_pairs(data: &[u8], num_pairs: u32, lg_k: u8) -> Result, Error> { if num_pairs == 0 { return Ok(vec![]); } @@ -187,7 +182,7 @@ pub(super) fn decode_pairs(data: &[u8], num_pairs: u32, lg_k: u8) -> Result Result, Error> { +pub fn decode_window(data: &[u8], lg_k: u8, num_coupons: u32) -> Result, Error> { let mut window = vec![0; 1 << lg_k]; let pseudo_phase = determine_pseudo_phase(lg_k, num_coupons); let decoding_table = &DECODING_TABLES_FOR_HIGH_ENTROPY_BYTE[pseudo_phase as usize]; @@ -274,7 +269,7 @@ impl<'a> BitReader<'a> { } } -pub(super) fn determine_pseudo_phase(lg_k: u8, num_coupons: u32) -> u8 { +pub fn determine_pseudo_phase(lg_k: u8, num_coupons: u32) -> u8 { let k = 1u64 << lg_k; let num_coupons = u64::from(num_coupons); // This mid-range logic produces pseudo-phases. They are used to select encoding tables. diff --git a/datasketches/src/cpc/compression_data.rs b/datasketches/src/cpc/compression_data.rs index 3c8c4648..3c9923e5 100644 --- a/datasketches/src/cpc/compression_data.rs +++ b/datasketches/src/cpc/compression_data.rs @@ -17,7 +17,7 @@ /// Notice that there are only 65 symbols here, which is different from our usual 8->12 coding /// scheme which handles 256 symbols. -pub(super) static LENGTH_LIMITED_UNARY_ENCODING_TABLE65: [u16; 65] = [ +pub static LENGTH_LIMITED_UNARY_ENCODING_TABLE65: [u16; 65] = [ // Length-limited "unary" code with 65 symbols. // entropy: 2.0 // avg_length: 2.0249023437500000000; max_length = 12; num_symbols = 65 @@ -92,7 +92,7 @@ pub(super) static LENGTH_LIMITED_UNARY_ENCODING_TABLE65: [u16; 65] = [ ]; /// Reverse mapping for the length-limited unary code with 65 symbols. -pub(super) static LENGTH_LIMITED_UNARY_DECODING_TABLE65: [u16; 4096] = [ +pub static LENGTH_LIMITED_UNARY_DECODING_TABLE65: [u16; 4096] = [ 256, 513, 256, 770, 256, 513, 256, 1027, 256, 513, 256, 770, 256, 513, 256, 1284, 256, 513, 256, 770, 256, 513, 256, 1027, 256, 513, 256, 770, 256, 513, 256, 1797, 256, 513, 256, 770, 256, 513, 256, 1027, 256, 513, 256, 770, 256, 513, 256, 1284, 256, 513, 256, 770, 256, 513, @@ -336,7 +336,7 @@ pub(super) static LENGTH_LIMITED_UNARY_DECODING_TABLE65: [u16; 4096] = [ /// encoding for rows containing more than one surprising bit). /// /// These permutations were created by the ocaml program "generatePermutationsForSLIDING.ml". -pub(super) static COLUMN_PERMUTATIONS_FOR_ENCODING: [[u8; 56]; 16] = [ +pub static COLUMN_PERMUTATIONS_FOR_ENCODING: [[u8; 56]; 16] = [ // for phase = 1 / 32 [ 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, @@ -436,7 +436,7 @@ pub(super) static COLUMN_PERMUTATIONS_FOR_ENCODING: [[u8; 56]; 16] = [ ]; /// Reverse mapping for column permutations. -pub(super) static COLUMN_PERMUTATIONS_FOR_DECODING: [[u8; 56]; 16] = [ +pub static COLUMN_PERMUTATIONS_FOR_DECODING: [[u8; 56]; 16] = [ [ 0, 1, 2, 3, 55, 4, 5, 6, 7, 8, 9, 10, 11, 12, 54, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 53, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, @@ -532,7 +532,7 @@ pub(super) static COLUMN_PERMUTATIONS_FOR_DECODING: [[u8; 56]; 16] = [ /// /// Only the encoding tables are defined by this file. The decoding tables (which are exact /// inverses) are created at library startup time. -pub(super) static ENCODING_TABLES_FOR_HIGH_ENTROPY_BYTE: [[u16; 256]; 22] = [ +pub static ENCODING_TABLES_FOR_HIGH_ENTROPY_BYTE: [[u16; 256]; 22] = [ // Sixteen Encoding Tables for the Steady State. // (table 0 of 22) (steady 0 of 16) (phase = 0.031250000 = 1.0 / 32.0) @@ -6326,7 +6326,7 @@ pub(super) static ENCODING_TABLES_FOR_HIGH_ENTROPY_BYTE: [[u16; 256]; 22] = [ ]; /// Reverse mapping for high entropy byte encoding tables. -pub(super) static DECODING_TABLES_FOR_HIGH_ENTROPY_BYTE: [[u16; 4096]; 22] = [ +pub static DECODING_TABLES_FOR_HIGH_ENTROPY_BYTE: [[u16; 4096]; 22] = [ [ 519, 1035, 771, 1567, 519, 1293, 783, 2081, 519, 1281, 771, 1809, 519, 1303, 783, 2609, 519, 1035, 771, 1575, 519, 1299, 783, 2304, 519, 1285, 771, 1859, 519, 1545, 783, 3186, diff --git a/datasketches/src/cpc/estimator.rs b/datasketches/src/cpc/estimator.rs index ef00b0b5..20e98660 100644 --- a/datasketches/src/cpc/estimator.rs +++ b/datasketches/src/cpc/estimator.rs @@ -88,7 +88,7 @@ static HIP_HIGH_SIDE_DATA: [u16; 33] = [ 5880, 5914, 5953, // 14 1000297 ]; -pub(super) fn estimate(merge_flag: bool, hip_est_accum: f64, lg_k: u8, num_coupons: u32) -> f64 { +pub fn estimate(merge_flag: bool, hip_est_accum: f64, lg_k: u8, num_coupons: u32) -> f64 { if !merge_flag { hip_est_accum } else { @@ -96,7 +96,7 @@ pub(super) fn estimate(merge_flag: bool, hip_est_accum: f64, lg_k: u8, num_coupo } } -pub(super) fn lower_bound( +pub fn lower_bound( merge_flag: bool, hip_est_accum: f64, lg_k: u8, @@ -110,7 +110,7 @@ pub(super) fn lower_bound( } } -pub(super) fn upper_bound( +pub fn upper_bound( merge_flag: bool, hip_est_accum: f64, lg_k: u8, diff --git a/datasketches/src/cpc/kxp_byte_lookup.rs b/datasketches/src/cpc/kxp_byte_lookup.rs index 31e21858..3032c462 100644 --- a/datasketches/src/cpc/kxp_byte_lookup.rs +++ b/datasketches/src/cpc/kxp_byte_lookup.rs @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License. -pub(super) static KXP_BYTE_TABLE: [f64; 256] = [ +pub static KXP_BYTE_TABLE: [f64; 256] = [ 0.99609375, 0.49609375, 0.74609375, 0.24609375, 0.87109375, 0.37109375, 0.62109375, 0.12109375, 0.93359375, 0.43359375, 0.68359375, 0.18359375, 0.80859375, 0.30859375, 0.55859375, 0.05859375, 0.96484375, 0.46484375, 0.71484375, 0.21484375, 0.83984375, 0.33984375, 0.58984375, 0.08984375, diff --git a/datasketches/src/cpc/pair_table.rs b/datasketches/src/cpc/pair_table.rs index 8c0fb62c..a476ec1f 100644 --- a/datasketches/src/cpc/pair_table.rs +++ b/datasketches/src/cpc/pair_table.rs @@ -27,7 +27,7 @@ const DOWNSIZE_DENOMINATOR: u32 = 4; /// This table stores `(row, col)` pairs and uses linear probing for collision resolution. It is /// optimized for scenarios where the cardinality of entries is low. #[derive(Debug, Clone)] -pub(super) struct PairTable { +pub struct PairTable { /// log2 of number of slots lg_size: u8, num_valid_bits: u8, diff --git a/datasketches/src/cpc/serialization.rs b/datasketches/src/cpc/serialization.rs index 3267ec3b..36d25d34 100644 --- a/datasketches/src/cpc/serialization.rs +++ b/datasketches/src/cpc/serialization.rs @@ -15,13 +15,13 @@ // specific language governing permissions and limitations // under the License. -pub(super) const SERIAL_VERSION: u8 = 1; -pub(super) const FLAG_COMPRESSED: u8 = 1; -pub(super) const FLAG_HAS_HIP: u8 = 2; -pub(super) const FLAG_HAS_TABLE: u8 = 3; -pub(super) const FLAG_HAS_WINDOW: u8 = 4; +pub const SERIAL_VERSION: u8 = 1; +pub const FLAG_COMPRESSED: u8 = 1; +pub const FLAG_HAS_HIP: u8 = 2; +pub const FLAG_HAS_TABLE: u8 = 3; +pub const FLAG_HAS_WINDOW: u8 = 4; -pub(super) fn make_preamble_ints( +pub fn make_preamble_ints( num_coupons: u32, has_hip: bool, has_table: bool, diff --git a/datasketches/src/cpc/sketch.rs b/datasketches/src/cpc/sketch.rs index 417512ad..8ebaeb42 100644 --- a/datasketches/src/cpc/sketch.rs +++ b/datasketches/src/cpc/sketch.rs @@ -249,7 +249,7 @@ impl CpcSketch { .expect("surprising value table must be initialized") } - pub(super) fn surprising_value_table_mut(&mut self) -> &mut PairTable { + fn surprising_value_table_mut(&mut self) -> &mut PairTable { self.surprising_value_table .as_mut() .expect("surprising value table must be initialized") diff --git a/datasketches/src/frequencies/reverse_purge_item_hash_map.rs b/datasketches/src/frequencies/reverse_purge_item_hash_map.rs index 4c06849e..f32e9ab1 100644 --- a/datasketches/src/frequencies/reverse_purge_item_hash_map.rs +++ b/datasketches/src/frequencies/reverse_purge_item_hash_map.rs @@ -32,7 +32,7 @@ const MAX_SAMPLE_SIZE: usize = 1024; /// Linear-probing hash map for (item, count) pairs with reverse purge support. #[derive(Debug, Clone)] -pub(super) struct ReversePurgeItemHashMap { +pub struct ReversePurgeItemHashMap { lg_length: u8, load_threshold: usize, keys: Vec>, diff --git a/datasketches/src/hash/seed.rs b/datasketches/src/hash/seed.rs index f3a31a08..b384d8a9 100644 --- a/datasketches/src/hash/seed.rs +++ b/datasketches/src/hash/seed.rs @@ -27,7 +27,7 @@ use crate::hash::MurmurHash3X64128; /// # Errors /// /// Returns an error of `error_kind` if the computed seed hash is zero. -pub(crate) fn compute_seed_hash(seed: u64, error_kind: ErrorKind) -> Result { +pub fn compute_seed_hash(seed: u64, error_kind: ErrorKind) -> Result { use std::hash::Hasher; let mut hasher = MurmurHash3X64128::with_seed(0); @@ -44,7 +44,7 @@ pub(crate) fn compute_seed_hash(seed: u64, error_kind: ErrorKind) -> Result Self { + pub fn from_header(compact: bool, lg_arr: u8) -> Self { if compact { Self::Compact } else { @@ -106,7 +106,7 @@ impl Array4 { /// Returns the true register value: /// * If raw < 15: value = cur_min + raw /// * If raw == 15 (AUX_TOKEN): value is in aux_map - pub(super) fn get(&self, slot: u32) -> u8 { + pub fn get(&self, slot: u32) -> u8 { let raw = self.get_raw(slot); if raw < AUX_TOKEN { @@ -121,12 +121,12 @@ impl Array4 { } /// Get the number of registers (K = 2^lg_config_k) - pub(super) fn num_registers(&self) -> usize { + pub fn num_registers(&self) -> usize { 1 << self.lg_config_k } /// Returns the estimate state independently from register-derived cached values. - pub(super) fn estimate_state(&self) -> EstimateState { + pub fn estimate_state(&self) -> EstimateState { self.estimator.estimate_state() } @@ -298,7 +298,7 @@ impl Array4 { } /// Restores estimate state after copying or transforming the same logical sketch. - pub(super) fn restore_estimate_state(&mut self, state: EstimateState) { + pub fn restore_estimate_state(&mut self, state: EstimateState) { self.estimator.restore_estimate_state(state); } diff --git a/datasketches/src/hll/array6.rs b/datasketches/src/hll/array6.rs index 5ab56572..70c519fc 100644 --- a/datasketches/src/hll/array6.rs +++ b/datasketches/src/hll/array6.rs @@ -82,17 +82,17 @@ impl Array6 { /// Get the unpacked 6-bit value (0-63) at the given slot #[inline] - pub(super) fn get(&self, slot: u32) -> u8 { + pub fn get(&self, slot: u32) -> u8 { self.get_raw(slot) } /// Get the number of registers (K = 2^lg_config_k) - pub(super) fn num_registers(&self) -> usize { + pub fn num_registers(&self) -> usize { 1 << self.lg_config_k } /// Returns the estimate state independently from register-derived cached values. - pub(super) fn estimate_state(&self) -> EstimateState { + pub fn estimate_state(&self) -> EstimateState { self.estimator.estimate_state() } @@ -164,7 +164,7 @@ impl Array6 { } /// Restores estimate state after copying or transforming the same logical sketch. - pub(super) fn restore_estimate_state(&mut self, state: EstimateState) { + pub fn restore_estimate_state(&mut self, state: EstimateState) { self.estimator.restore_estimate_state(state); } diff --git a/datasketches/src/hll/array8.rs b/datasketches/src/hll/array8.rs index 8a3b61c7..56756400 100644 --- a/datasketches/src/hll/array8.rs +++ b/datasketches/src/hll/array8.rs @@ -123,22 +123,22 @@ impl Array8 { } /// Get read access to register values (one byte per register) - pub(super) fn values(&self) -> &[u8] { + pub fn values(&self) -> &[u8] { &self.bytes } /// Get the number of registers (K = 2^lg_config_k) - pub(super) fn num_registers(&self) -> usize { + pub fn num_registers(&self) -> usize { 1 << self.lg_config_k } /// Returns the estimate state independently from register-derived cached values. - pub(super) fn estimate_state(&self) -> EstimateState { + pub fn estimate_state(&self) -> EstimateState { self.estimator.estimate_state() } /// Restores estimate state after copying or transforming the same logical sketch. - pub(super) fn restore_estimate_state(&mut self, state: EstimateState) { + pub fn restore_estimate_state(&mut self, state: EstimateState) { self.estimator.restore_estimate_state(state); } @@ -146,7 +146,7 @@ impl Array8 { /// /// This bypasses the normal update path and directly modifies the register. /// Caller must call rebuild_estimator_from_registers() after all modifications. - pub(super) fn set_register(&mut self, slot: usize, value: u8) { + pub fn set_register(&mut self, slot: usize, value: u8) { self.bytes[slot] = value; } @@ -154,7 +154,7 @@ impl Array8 { /// /// Recomputes num_zeros, kxq0, and kxq1, then switches to composite estimation. /// Should be called after bulk register modifications. - pub(super) fn rebuild_estimator_from_registers(&mut self) { + pub fn rebuild_estimator_from_registers(&mut self) { self.rebuild_cached_values(); self.estimator.invalidate_hip(); } @@ -167,7 +167,7 @@ impl Array8 { /// # Panics /// /// Panics if src length doesn't match self length (different lg_k). - pub(super) fn merge_array_same_lgk(&mut self, src: &[u8]) { + pub fn merge_array_same_lgk(&mut self, src: &[u8]) { assert_eq!( src.len(), self.bytes.len(), @@ -198,7 +198,7 @@ impl Array8 { /// # Panics /// /// Panics if src_lg_k <= self.lg_config_k (not downsampling). - pub(super) fn merge_array_with_downsample(&mut self, src: &[u8], src_lg_k: u8) { + pub fn merge_array_with_downsample(&mut self, src: &[u8], src_lg_k: u8) { assert!( src_lg_k > self.lg_config_k, "Source lg_k must be greater than destination lg_k for downsampling" diff --git a/datasketches/src/hll/estimator.rs b/datasketches/src/hll/estimator.rs index f607e8e1..8897516d 100644 --- a/datasketches/src/hll/estimator.rs +++ b/datasketches/src/hll/estimator.rs @@ -28,7 +28,7 @@ use crate::hll::harmonic_numbers; /// Selects the estimate that is valid for the current register history. #[derive(Debug, Clone, Copy, PartialEq)] -pub(super) enum EstimateState { +pub enum EstimateState { /// The register updates have a known order, so the HIP accumulator is valid. Hip(f64), /// A bulk merge lost the update order, so the estimate must come from the registers. @@ -61,12 +61,7 @@ impl Estimator { } /// Restores estimator fields from an HLL serialization preamble. - pub(super) fn from_serialized( - hip_accum: f64, - kxq0: f64, - kxq1: f64, - out_of_order: bool, - ) -> Self { + pub fn from_serialized(hip_accum: f64, kxq0: f64, kxq1: f64, out_of_order: bool) -> Self { let estimate_state = if out_of_order { EstimateState::Composite } else { @@ -325,22 +320,22 @@ impl Estimator { } /// Returns the estimate state independently from register-derived KxQ values. - pub(super) fn estimate_state(&self) -> EstimateState { + pub fn estimate_state(&self) -> EstimateState { self.estimate_state } /// Restores estimate state after copying or transforming the same logical sketch. - pub(super) fn restore_estimate_state(&mut self, state: EstimateState) { + pub fn restore_estimate_state(&mut self, state: EstimateState) { self.estimate_state = state; } /// Invalidates HIP after registers from independent histories are merged. - pub(super) fn invalidate_hip(&mut self) { + pub fn invalidate_hip(&mut self) { self.estimate_state = EstimateState::Composite; } /// Replaces register-derived KxQ values after a bulk register operation. - pub(super) fn restore_kxq(&mut self, kxq0: f64, kxq1: f64) { + pub fn restore_kxq(&mut self, kxq0: f64, kxq1: f64) { self.kxq0 = kxq0; self.kxq1 = kxq1; } diff --git a/datasketches/src/req/compactor.rs b/datasketches/src/req/compactor.rs index e4835dc1..cc92cd24 100644 --- a/datasketches/src/req/compactor.rs +++ b/datasketches/src/req/compactor.rs @@ -33,7 +33,7 @@ use crate::req::value::ReqValue; /// When the compactor reaches its nominal capacity, it performs compaction /// by keeping approximately half the items and promoting the rest to the next level. #[derive(Debug, Clone)] -pub(super) struct Compactor { +pub struct Compactor { /// Current items in the compactor items: Vec, /// Whether items are currently sorted @@ -68,7 +68,7 @@ where /// * `lg_weight` - The level (log weight) of this compactor /// * `k` - The k parameter from the parent sketch /// * `rank_accuracy` - Rank accuracy configuration - pub(super) fn new(lg_weight: u8, k: u16, rank_accuracy: RankAccuracy) -> Self { + pub fn new(lg_weight: u8, k: u16, rank_accuracy: RankAccuracy) -> Self { let section_size_raw = k as f32; let section_size = nearest_even_section_size(section_size_raw); let num_sections = INITIAL_SECTIONS_PER_COMPACTOR; @@ -92,23 +92,23 @@ where } /// Returns the number of items currently in this compactor. - pub(super) fn num_items(&self) -> u32 { + pub fn num_items(&self) -> u32 { self.items.len() as u32 } /// Returns the nominal capacity of this compactor. - pub(super) fn nominal_capacity(&self) -> u32 { + pub fn nominal_capacity(&self) -> u32 { 2 * self.section_size * self.num_sections as u32 } /// Returns whether the items are currently sorted. - pub(super) fn is_sorted(&self) -> bool { + pub fn is_sorted(&self) -> bool { self.is_sorted } /// Appends an item to this compactor. #[inline(always)] - pub(super) fn append(&mut self, item: T) { + pub fn append(&mut self, item: T) { self.items.push(item); if self.items.len() > 1 { self.is_sorted = false; @@ -116,7 +116,7 @@ where } /// Merges items from another compactor into this one. - pub(super) fn merge(&mut self, other: &Self) { + pub fn merge(&mut self, other: &Self) { debug_assert_eq!(self.lg_weight, other.lg_weight); self.state |= other.state; if !other.items.is_empty() { @@ -140,7 +140,7 @@ where /// Uses binary search when this compactor is sorted, and a linear scan /// otherwise. This lets [`ReqSketch::rank`](crate::req::ReqSketch::rank) sum /// per-level weights directly without first building a sorted view. - pub(super) fn count_below(&self, item: &T, inclusive: bool) -> usize { + pub fn count_below(&self, item: &T, inclusive: bool) -> usize { if self.is_sorted { if inclusive { self.items.partition_point(|x| x <= item) @@ -159,7 +159,7 @@ where /// Merges sorted items into this compactor using scratch buffer to avoid allocation. /// Both this compactor's items and the input must be sorted. #[inline(always)] - pub(super) fn merge_sorted(&mut self, items: &[T]) { + pub fn merge_sorted(&mut self, items: &[T]) { if items.is_empty() { return; } @@ -208,7 +208,7 @@ where /// Sorts the items in this compactor if not already sorted. #[inline(always)] - pub(super) fn sort(&mut self) { + pub fn sort(&mut self) { if !self.is_sorted { // Use unstable sort for better performance (stable not needed for REQ sketch) self.items.sort_unstable(); @@ -220,7 +220,7 @@ where /// Writes promoted items into `out` and removes the compacted range in-place via `copy_within + /// truncate`. #[inline(always)] - pub(super) fn compact_into(&mut self, _rank_accuracy: RankAccuracy, out: &mut Vec) { + pub fn compact_into(&mut self, _rank_accuracy: RankAccuracy, out: &mut Vec) { if self.items.is_empty() { out.clear(); return; @@ -271,17 +271,17 @@ where } /// Returns an iterator over the items in this compactor. - pub(super) fn iter(&self) -> impl Iterator { + pub fn iter(&self) -> impl Iterator { self.items.iter() } /// Returns a slice of items for zero-allocation iteration. - pub(super) fn items_slice(&self) -> &[T] { + pub fn items_slice(&self) -> &[T] { &self.items } /// Returns the weight (2^lg_weight) for items in this compactor. - pub(super) fn weight(&self) -> u64 { + pub fn weight(&self) -> u64 { 1u64 << self.lg_weight } @@ -349,7 +349,7 @@ where } /// Serialize this compactor (preamble + items) into the byte buffer. - pub(super) fn serialize_into(&self, bytes: &mut crate::codec::SketchBytes) + pub fn serialize_into(&self, bytes: &mut crate::codec::SketchBytes) where T: ReqValue, { @@ -365,7 +365,7 @@ where } /// Deserialize a compactor (preamble + items) from the byte cursor. - pub(super) fn deserialize( + pub fn deserialize( cursor: &mut crate::codec::SketchSlice<'_>, k: u16, expected_lg_weight: u8, @@ -432,7 +432,7 @@ where /// helper synthesises a fresh compactor and seeds it with the deserialized items. /// A false wire flag stays false for byte-stable C++/Java round trips; a true flag /// is cleared if the items are not actually sorted. - pub(super) fn raw_items_compactor( + pub fn raw_items_compactor( k: u16, rank_accuracy: RankAccuracy, items: Vec, @@ -451,7 +451,7 @@ where /// buffer) is reset; the deterministic `state` counter and the persistent /// configuration (`lg_weight`, `section_size_raw`, `num_sections`) are preserved /// from the wire data. - pub(super) fn from_serialized_state( + fn from_serialized_state( lg_weight: u8, section_size_raw: f32, num_sections: u8, @@ -476,21 +476,6 @@ where } #[cfg(test)] -impl Compactor -where - T: Clone + Ord, -{ - /// Returns the level (log weight) of this compactor. Test-only accessor. - pub(super) fn lg_weight(&self) -> u8 { - self.lg_weight - } - - /// Returns the current state for deterministic compaction. Test-only accessor. - pub(super) fn state(&self) -> u64 { - self.state - } -} - #[cfg(test)] mod tests { use googletest::assert_that; @@ -502,7 +487,7 @@ mod tests { #[test] fn test_new_compactor() { let compactor: Compactor = Compactor::new(0, 12, RankAccuracy::HighRank); - assert_eq!(compactor.lg_weight(), 0); + assert_eq!(compactor.lg_weight, 0); assert_eq!(compactor.num_items(), 0); assert!(compactor.is_sorted()); assert_eq!(compactor.weight(), 1); @@ -582,8 +567,8 @@ mod tests { .unwrap(); assert_eq!(c.num_items(), c2.num_items()); - assert_eq!(c.lg_weight(), c2.lg_weight()); - assert_eq!(c.state(), c2.state()); + assert_eq!(c.lg_weight, c2.lg_weight); + assert_eq!(c.state, c2.state); let xs: Vec> = c.iter().copied().collect(); let ys: Vec> = c2.iter().copied().collect(); assert_eq!(xs, ys); diff --git a/datasketches/src/req/serialization.rs b/datasketches/src/req/serialization.rs index 2d56a5ed..90c949a4 100644 --- a/datasketches/src/req/serialization.rs +++ b/datasketches/src/req/serialization.rs @@ -24,17 +24,17 @@ use crate::req::INITIAL_SECTIONS_PER_COMPACTOR; use crate::req::MIN_K; use crate::req::nearest_even_section_size; -pub(super) const SERIAL_VERSION: u8 = 1; -pub(super) const PREAMBLE_INTS_EXACT: u8 = 2; -pub(super) const PREAMBLE_INTS_ESTIMATION: u8 = 4; -pub(super) const RAW_ITEMS_THRESHOLD: u64 = 4; +pub const SERIAL_VERSION: u8 = 1; +pub const PREAMBLE_INTS_EXACT: u8 = 2; +pub const PREAMBLE_INTS_ESTIMATION: u8 = 4; +pub const RAW_ITEMS_THRESHOLD: u64 = 4; /// Flag bits — match the C++ enum order: RESERVED1, RESERVED2, IS_EMPTY, IS_HIGH_RANK, RAW_ITEMS, /// IS_LEVEL_ZERO_SORTED. -pub(super) const FLAG_IS_EMPTY: u8 = 1 << 2; -pub(super) const FLAG_IS_HIGH_RANK: u8 = 1 << 3; -pub(super) const FLAG_RAW_ITEMS: u8 = 1 << 4; -pub(super) const FLAG_IS_LEVEL_ZERO_SORTED: u8 = 1 << 5; +pub const FLAG_IS_EMPTY: u8 = 1 << 2; +pub const FLAG_IS_HIGH_RANK: u8 = 1 << 3; +pub const FLAG_RAW_ITEMS: u8 = 1 << 4; +pub const FLAG_IS_LEVEL_ZERO_SORTED: u8 = 1 << 5; fn section_growth_threshold(num_sections: u8) -> Option { num_sections @@ -59,7 +59,7 @@ fn has_reachable_section_count(state: u64, num_sections: u8) -> bool { sections == num_sections } -pub(super) fn validate_compactor_state( +pub fn validate_compactor_state( k: u16, expected_lg_weight: u8, state: u64, @@ -84,11 +84,11 @@ pub(super) fn validate_compactor_state( Ok(()) } -pub(super) fn check_serial_version(actual: u8) -> Result<(), Error> { +pub fn check_serial_version(actual: u8) -> Result<(), Error> { ensure_serial_version_is(SERIAL_VERSION, actual) } -pub(super) fn check_preamble_ints(actual: u8, num_levels: u8) -> Result<(), Error> { +pub fn check_preamble_ints(actual: u8, num_levels: u8) -> Result<(), Error> { let expected = if num_levels > 1 { PREAMBLE_INTS_ESTIMATION } else { diff --git a/datasketches/src/req/sketch.rs b/datasketches/src/req/sketch.rs index 1a2e2635..e2f1d944 100644 --- a/datasketches/src/req/sketch.rs +++ b/datasketches/src/req/sketch.rs @@ -470,7 +470,7 @@ where .sum() } - pub(super) fn flags_byte(&self) -> u8 { + fn flags_byte(&self) -> u8 { let mut flags = 0u8; if self.is_empty() { flags |= FLAG_IS_EMPTY; @@ -487,7 +487,7 @@ where flags } - pub(super) fn is_raw_items(&self) -> bool { + fn is_raw_items(&self) -> bool { self.n <= RAW_ITEMS_THRESHOLD && self.compactors.len() == 1 } diff --git a/datasketches/src/tdigest/serialization.rs b/datasketches/src/tdigest/serialization.rs index 407e2acd..debe6786 100644 --- a/datasketches/src/tdigest/serialization.rs +++ b/datasketches/src/tdigest/serialization.rs @@ -15,13 +15,13 @@ // specific language governing permissions and limitations // under the License. -pub(super) const PREAMBLE_LONGS_EMPTY_OR_SINGLE: u8 = 1; -pub(super) const PREAMBLE_LONGS_MULTIPLE: u8 = 2; -pub(super) const SERIAL_VERSION: u8 = 1; -pub(super) const FLAGS_IS_EMPTY: u8 = 1 << 0; -pub(super) const FLAGS_IS_SINGLE_VALUE: u8 = 1 << 1; -pub(super) const FLAGS_REVERSE_MERGE: u8 = 1 << 2; +pub const PREAMBLE_LONGS_EMPTY_OR_SINGLE: u8 = 1; +pub const PREAMBLE_LONGS_MULTIPLE: u8 = 2; +pub const SERIAL_VERSION: u8 = 1; +pub const FLAGS_IS_EMPTY: u8 = 1 << 0; +pub const FLAGS_IS_SINGLE_VALUE: u8 = 1 << 1; +pub const FLAGS_REVERSE_MERGE: u8 = 1 << 2; /// the format of the reference implementation is using double (f64) precision -pub(super) const COMPAT_DOUBLE: u32 = 1; +pub const COMPAT_DOUBLE: u32 = 1; /// the format of the reference implementation is using float (f32) precision -pub(super) const COMPAT_FLOAT: u32 = 2; +pub const COMPAT_FLOAT: u32 = 2; diff --git a/datasketches/src/tdigest/sketch.rs b/datasketches/src/tdigest/sketch.rs index 19f8bf39..bd27a4c0 100644 --- a/datasketches/src/tdigest/sketch.rs +++ b/datasketches/src/tdigest/sketch.rs @@ -1544,15 +1544,15 @@ fn checked_weight_sum(total_weight: u64, weight: u64) -> Result { /// /// Corresponds to K_2 in the reference implementation mod scale_function { - pub(super) fn max(q: f64, normalizer: f64) -> f64 { + pub fn max(q: f64, normalizer: f64) -> f64 { q * (1. - q) / normalizer } - pub(super) fn normalizer(compression: f64, n: f64) -> f64 { + pub fn normalizer(compression: f64, n: f64) -> f64 { compression / z(compression, n) } - pub(super) fn z(compression: f64, n: f64) -> f64 { + pub fn z(compression: f64, n: f64) -> f64 { 4. * (n / compression).ln() + 24. } } diff --git a/datasketches/src/thetafamily/theta/bit_pack.rs b/datasketches/src/thetafamily/theta/bit_pack.rs index d64e59e9..7096bbc3 100644 --- a/datasketches/src/thetafamily/theta/bit_pack.rs +++ b/datasketches/src/thetafamily/theta/bit_pack.rs @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License. -pub(super) const BLOCK_WIDTH: usize = 8; +pub const BLOCK_WIDTH: usize = 8; #[inline] fn low_bit_to_byte_mask(bits: u8) -> u8 { @@ -33,7 +33,7 @@ fn low_bit_to_byte_mask(bits: u8) -> u8 { /// Panics if the buffer is too small to hold the packed values. /// The caller must ensure that `bytes` has enough capacity for /// the total number of bits to be packed. -pub(super) struct BitPacker<'a> { +pub struct BitPacker<'a> { bytes: &'a mut [u8], byte_index: usize, byte_bit_used: u8, @@ -104,7 +104,7 @@ impl<'a> BitPacker<'a> { /// Panics if the buffer is too small to provide the requested bits. /// The caller must ensure that `bytes` has enough capacity for /// the total number of bits to be unpacked. -pub(super) struct BitUnpacker<'a> { +pub struct BitUnpacker<'a> { bytes: &'a [u8], byte_index: usize, byte_bit_used: u8, @@ -4965,7 +4965,7 @@ fn unpack_bits_63(values: &mut [u64], bytes: &[u8]) { /// * Panics if `values.len()` is not equal to `BLOCK_WIDTH`. /// * Panics if `bits` is not in the range `1..=63`. /// * Panics if `bytes.len()` is less than `bits`. -pub(super) fn pack_bits_block(values: &[u64], bytes: &mut [u8], bits: u8) { +pub fn pack_bits_block(values: &[u64], bytes: &mut [u8], bits: u8) { assert_eq!(values.len(), BLOCK_WIDTH, "values length must be 8"); assert!( (1..=63).contains(&bits), @@ -5048,7 +5048,7 @@ pub(super) fn pack_bits_block(values: &[u64], bytes: &mut [u8], bits: u8) { /// * Panics if `values.len()` is not equal to `BLOCK_WIDTH`. /// * Panics if `bits` is not in the range `1..=63`. /// * Panics if `bytes.len()` is less than `bits`. -pub(super) fn unpack_bits_block(values: &mut [u64], bytes: &[u8], bits: u8) { +pub fn unpack_bits_block(values: &mut [u64], bytes: &[u8], bits: u8) { assert_eq!(values.len(), BLOCK_WIDTH, "values length must be 8"); assert!( (1..=63).contains(&bits), diff --git a/datasketches/src/thetafamily/theta/hash_table.rs b/datasketches/src/thetafamily/theta/hash_table.rs index 6cd17353..3c96b3c3 100644 --- a/datasketches/src/thetafamily/theta/hash_table.rs +++ b/datasketches/src/thetafamily/theta/hash_table.rs @@ -28,7 +28,7 @@ use crate::thetacommon::hash_table::SketchHashTable; /// * After it reaches the capacity bigger than 2^lg_nom_size, every time the number of entries /// exceeds the threshold, it will rebuild the table: only keep the min 2^lg_nom_size entries and /// update the theta to the k-th smallest entry. -pub(super) type ThetaHashTable = SketchHashTable; +pub type ThetaHashTable = SketchHashTable; /// A retained entry in a Theta sketch. #[derive(Debug, Clone, Copy)] diff --git a/datasketches/src/thetafamily/theta/serialization.rs b/datasketches/src/thetafamily/theta/serialization.rs index 54ba181c..f9d6e2cd 100644 --- a/datasketches/src/thetafamily/theta/serialization.rs +++ b/datasketches/src/thetafamily/theta/serialization.rs @@ -17,9 +17,9 @@ //! Binary serialization format constants for Theta sketches. -pub(super) const UNCOMPRESSED_SERIAL_VERSION: u8 = 3; -pub(super) const COMPRESSED_SERIAL_VERSION: u8 = 4; +pub const UNCOMPRESSED_SERIAL_VERSION: u8 = 3; +pub const COMPRESSED_SERIAL_VERSION: u8 = 4; -pub(super) const V2_PREAMBLE_EMPTY: u8 = 1; -pub(super) const V2_PREAMBLE_PRECISE: u8 = 2; -pub(super) const V2_PREAMBLE_ESTIMATE: u8 = 3; +pub const V2_PREAMBLE_EMPTY: u8 = 1; +pub const V2_PREAMBLE_PRECISE: u8 = 2; +pub const V2_PREAMBLE_ESTIMATE: u8 = 3; diff --git a/datasketches/src/thetafamily/tuple/hash_table.rs b/datasketches/src/thetafamily/tuple/hash_table.rs index 04b26f6e..638d0c7f 100644 --- a/datasketches/src/thetafamily/tuple/hash_table.rs +++ b/datasketches/src/thetafamily/tuple/hash_table.rs @@ -61,7 +61,7 @@ impl TupleEntry { /// This is the Theta sketch hash table extended so that each retained key carries a user-defined /// summary. Unlike the Theta hash table, when a key is inserted that already exists, the incoming /// update is merged into the existing summary rather than discarded. -pub(super) type TupleHashTable = SketchHashTable>; +pub type TupleHashTable = SketchHashTable>; impl SketchEntry for TupleEntry { fn hash(&self) -> u64 { diff --git a/datasketches/src/thetafamily/tuple/serialization.rs b/datasketches/src/thetafamily/tuple/serialization.rs index 5798883f..b077f0c4 100644 --- a/datasketches/src/thetafamily/tuple/serialization.rs +++ b/datasketches/src/thetafamily/tuple/serialization.rs @@ -30,14 +30,14 @@ use crate::codec::SketchSlice; use crate::error::Error; /// Current serial version written by this implementation. -pub(super) const SERIAL_VERSION: u8 = 3; +pub const SERIAL_VERSION: u8 = 3; /// Legacy serial version still accepted on read. -pub(super) const SERIAL_VERSION_LEGACY: u8 = 1; +pub const SERIAL_VERSION_LEGACY: u8 = 1; /// Current sketch-type byte written by this implementation. -pub(super) const SKETCH_TYPE: u8 = 1; +pub const SKETCH_TYPE: u8 = 1; /// Legacy sketch-type byte still accepted on read. -pub(super) const SKETCH_TYPE_LEGACY: u8 = 5; +pub const SKETCH_TYPE_LEGACY: u8 = 5; /// Trait for values that can be stored as Tuple sketch summaries. /// From 27037867ba0fec375465bd3cc3fc05de7f28131d Mon Sep 17 00:00:00 2001 From: tison Date: Sat, 29 Aug 2026 16:05:13 +0800 Subject: [PATCH 2/2] chore: remove duplicate test attribute --- datasketches/src/req/compactor.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/datasketches/src/req/compactor.rs b/datasketches/src/req/compactor.rs index cc92cd24..a81acf70 100644 --- a/datasketches/src/req/compactor.rs +++ b/datasketches/src/req/compactor.rs @@ -475,7 +475,6 @@ where } } -#[cfg(test)] #[cfg(test)] mod tests { use googletest::assert_that;