From b01b31a72b7ff738775cc7d09b9551b33eabd9c9 Mon Sep 17 00:00:00 2001 From: tison Date: Mon, 9 Nov 2026 16:00:00 +0800 Subject: [PATCH 1/7] docs(countmin): explain empty updates and queries --- datasketches/src/countmin/sketch.rs | 47 +++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/datasketches/src/countmin/sketch.rs b/datasketches/src/countmin/sketch.rs index f36b2fee..92121da1 100644 --- a/datasketches/src/countmin/sketch.rs +++ b/datasketches/src/countmin/sketch.rs @@ -51,8 +51,51 @@ const MAX_TABLE_ENTRIES: usize = 1 << 30; /// For cross-language version 2 interchange, use `i64` counters and encode inputs consistently: /// * `i64` and `u64` values are hashed as eight little-endian bytes; use /// [`crate::hash::value::natural_extend`] for narrower integers. -/// * Use [`crate::hash::value::raw_bytes`] for UTF-8 strings and byte slices, and skip empty inputs -/// when interoperating with implementations that ignore them. +/// * Use [`crate::hash::value::raw_bytes`] for UTF-8 strings and byte slices. +/// +/// # Empty inputs +/// +/// Empty strings and byte slices are hashed like other inputs, including when wrapped in +/// `raw_bytes`. The wrapper selects the encoding; it does not skip updates or queries. +/// +/// To match the cross-language version 2 convention, callers skip empty string and byte-slice +/// updates and return zero for their estimates and both bounds without querying the sketch. +/// Filtering updates alone is insufficient: an empty query can collide with populated counters, +/// and the upper bound can include a nonzero error term even when the estimate is zero. +/// Version 1 data must retain the input handling used when it was created. +/// +/// # Examples +/// +/// Applies the empty-input convention to a string stream and query. Byte slices use the same +/// `is_empty()` checks with `raw_bytes::from_slice`. +/// +/// ``` +/// use datasketches::countmin::CountMinSketch; +/// use datasketches::hash::value::raw_bytes; +/// +/// let mut sketch = CountMinSketch::::new(3, 1000)?; +/// for input in ["", "apple", ""] { +/// let item = raw_bytes::from_str(input); +/// if !item.is_empty() { +/// sketch.update_with_weight(item, 5); +/// } +/// } +/// assert_eq!(sketch.total_weight(), 5); +/// assert_eq!(sketch.estimate(raw_bytes::from_str("apple")), 5); +/// +/// let item = raw_bytes::from_str(""); +/// let (estimate, lower, upper) = if item.is_empty() { +/// (0, 0, 0) +/// } else { +/// ( +/// sketch.estimate(item), +/// sketch.lower_bound(item), +/// sketch.upper_bound(item), +/// ) +/// }; +/// assert_eq!((estimate, lower, upper), (0, 0, 0)); +/// # Ok::<(), datasketches::error::Error>(()) +/// ``` #[derive(Debug, Clone, PartialEq)] pub struct CountMinSketch { num_hashes: u8, From 5876cc5951fd7ae9768f5a36e740f8f13b5e75ed Mon Sep 17 00:00:00 2001 From: tison Date: Mon, 9 Nov 2026 16:11:25 +0800 Subject: [PATCH 2/7] docs: align cross-language hashing guidance --- datasketches/src/bloom/mod.rs | 9 ++++ datasketches/src/countmin/mod.rs | 41 ++++++++++++++++--- datasketches/src/countmin/sketch.rs | 50 +---------------------- datasketches/src/cpc/mod.rs | 8 ++++ datasketches/src/hll/mod.rs | 10 ++++- datasketches/src/thetafamily/theta/mod.rs | 8 ++++ datasketches/src/thetafamily/tuple/mod.rs | 8 ++++ datasketches/src/xor/mod.rs | 14 ++++--- 8 files changed, 87 insertions(+), 61 deletions(-) diff --git a/datasketches/src/bloom/mod.rs b/datasketches/src/bloom/mod.rs index 5b2fbce2..1486fe1a 100644 --- a/datasketches/src/bloom/mod.rs +++ b/datasketches/src/bloom/mod.rs @@ -33,6 +33,15 @@ //! [`difference()`](BloomFilter::difference) excludes the right filter's items exactly, but //! may also drop left items whose hash positions collide with the right filter. //! +//! # Cross-language hashing +//! +//! Use [`hash::value`](crate::hash::value) wrappers to match input encodings across languages, +//! including `raw_bytes` for UTF-8 strings and byte slices. +//! +//! To match DataSketches Java, callers skip empty string inserts and return `false` for empty +//! string membership queries, including queries combined with insertion. Empty byte slices are +//! valid inputs and are not filtered. +//! //! # Usage //! //! ``` diff --git a/datasketches/src/countmin/mod.rs b/datasketches/src/countmin/mod.rs index 03c92838..3a16ff47 100644 --- a/datasketches/src/countmin/mod.rs +++ b/datasketches/src/countmin/mod.rs @@ -20,19 +20,48 @@ //! The CountMin sketch provides approximate frequency counts for streaming data //! with configurable relative error and confidence bounds. //! -//! Serial version 2 sketches with `i64` counters support cross-language binary interchange when -//! items use compatible hashing; see [`CountMinSketch`] and [`hash::value`](crate::hash::value). +//! # Cross-language hashing +//! +//! For cross-language version 2 interchange, use `i64` counters and compatible input encodings: +//! +//! * Use `i64`/`u64` for eight-byte little-endian integers and +//! [`natural_extend`](crate::hash::value::natural_extend) for narrower integers. +//! * Use [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices. +//! +//! The version 2 specification ignores empty strings and byte arrays. For cross-language use, +//! callers skip these updates and return zero for empty-input estimates and both bounds. //! //! # Usage //! +//! This example handles empty strings before updating or querying. Byte slices use the same +//! `is_empty()` checks with `raw_bytes::from_slice`. +//! //! ``` //! use datasketches::countmin::CountMinSketch; //! use datasketches::hash::value::raw_bytes; //! -//! let mut sketch = CountMinSketch::::new(5, 256).unwrap(); -//! sketch.update(raw_bytes::from_str("apple")); -//! sketch.update_with_weight(raw_bytes::from_str("banana"), 3); -//! assert!(sketch.estimate(raw_bytes::from_str("banana")) >= 3); +//! let mut sketch = CountMinSketch::::new(3, 1000)?; +//! for input in ["", "apple", ""] { +//! let item = raw_bytes::from_str(input); +//! if !item.is_empty() { +//! sketch.update_with_weight(item, 5); +//! } +//! } +//! assert_eq!(sketch.total_weight(), 5); +//! assert_eq!(sketch.estimate(raw_bytes::from_str("apple")), 5); +//! +//! let item = raw_bytes::from_str(""); +//! let (estimate, lower, upper) = if item.is_empty() { +//! (0, 0, 0) +//! } else { +//! ( +//! sketch.estimate(item), +//! sketch.lower_bound(item), +//! sketch.upper_bound(item), +//! ) +//! }; +//! assert_eq!((estimate, lower, upper), (0, 0, 0)); +//! # Ok::<(), datasketches::error::Error>(()) //! ``` //! //! # Configuration Helpers diff --git a/datasketches/src/countmin/sketch.rs b/datasketches/src/countmin/sketch.rs index 92121da1..350f9bc9 100644 --- a/datasketches/src/countmin/sketch.rs +++ b/datasketches/src/countmin/sketch.rs @@ -48,54 +48,8 @@ const MAX_TABLE_ENTRIES: usize = 1 << 30; /// New sketches use serial version 2. Deserialized version 1 sketches retain their legacy /// hashing and serialization format, and sketches of different versions cannot be merged. /// -/// For cross-language version 2 interchange, use `i64` counters and encode inputs consistently: -/// * `i64` and `u64` values are hashed as eight little-endian bytes; use -/// [`crate::hash::value::natural_extend`] for narrower integers. -/// * Use [`crate::hash::value::raw_bytes`] for UTF-8 strings and byte slices. -/// -/// # Empty inputs -/// -/// Empty strings and byte slices are hashed like other inputs, including when wrapped in -/// `raw_bytes`. The wrapper selects the encoding; it does not skip updates or queries. -/// -/// To match the cross-language version 2 convention, callers skip empty string and byte-slice -/// updates and return zero for their estimates and both bounds without querying the sketch. -/// Filtering updates alone is insufficient: an empty query can collide with populated counters, -/// and the upper bound can include a nonzero error term even when the estimate is zero. -/// Version 1 data must retain the input handling used when it was created. -/// -/// # Examples -/// -/// Applies the empty-input convention to a string stream and query. Byte slices use the same -/// `is_empty()` checks with `raw_bytes::from_slice`. -/// -/// ``` -/// use datasketches::countmin::CountMinSketch; -/// use datasketches::hash::value::raw_bytes; -/// -/// let mut sketch = CountMinSketch::::new(3, 1000)?; -/// for input in ["", "apple", ""] { -/// let item = raw_bytes::from_str(input); -/// if !item.is_empty() { -/// sketch.update_with_weight(item, 5); -/// } -/// } -/// assert_eq!(sketch.total_weight(), 5); -/// assert_eq!(sketch.estimate(raw_bytes::from_str("apple")), 5); -/// -/// let item = raw_bytes::from_str(""); -/// let (estimate, lower, upper) = if item.is_empty() { -/// (0, 0, 0) -/// } else { -/// ( -/// sketch.estimate(item), -/// sketch.lower_bound(item), -/// sketch.upper_bound(item), -/// ) -/// }; -/// assert_eq!((estimate, lower, upper), (0, 0, 0)); -/// # Ok::<(), datasketches::error::Error>(()) -/// ``` +/// For input encodings and empty-input handling, see +/// [Cross-language hashing](crate::countmin#cross-language-hashing). #[derive(Debug, Clone, PartialEq)] pub struct CountMinSketch { num_hashes: u8, diff --git a/datasketches/src/cpc/mod.rs b/datasketches/src/cpc/mod.rs index 6102deaf..eb4ad913 100644 --- a/datasketches/src/cpc/mod.rs +++ b/datasketches/src/cpc/mod.rs @@ -34,6 +34,14 @@ //! configurations of K. //! //! For additional security this sketch can be configured with a user-specified hash seed. +//! +//! # Cross-language hashing +//! +//! Use [`hash::value`](crate::hash::value) wrappers to match input encodings across languages, +//! including `raw_bytes` for UTF-8 strings and byte slices. +//! +//! To match DataSketches Java, callers skip empty strings and byte slices before updates. +//! To match DataSketches C++ string updates, callers skip empty strings. mod compression; mod compression_data; diff --git a/datasketches/src/hll/mod.rs b/datasketches/src/hll/mod.rs index 06db8d35..d9a9c6ec 100644 --- a/datasketches/src/hll/mod.rs +++ b/datasketches/src/hll/mod.rs @@ -21,8 +21,14 @@ //! [`HllType`] controls register storage; `lg_k` controls the register count and accuracy. //! //! The binary serialization format supports cross-language interchange. -//! Cross-language updates must also use compatible hashing; see -//! [`hash::value`](crate::hash::value). +//! +//! # Cross-language hashing +//! +//! Use [`hash::value`](crate::hash::value) wrappers to match input encodings across languages, +//! including `raw_bytes` for UTF-8 strings and byte slices. +//! +//! To match DataSketches Java, callers skip empty strings and byte slices before updates. +//! To match DataSketches C++ string updates, callers skip empty strings. //! //! # Usage //! diff --git a/datasketches/src/thetafamily/theta/mod.rs b/datasketches/src/thetafamily/theta/mod.rs index c65fa09e..9754841b 100644 --- a/datasketches/src/thetafamily/theta/mod.rs +++ b/datasketches/src/thetafamily/theta/mod.rs @@ -30,6 +30,14 @@ //! * [`ThetaSketch`]: Mutable sketch for building from input data. //! * [`CompactThetaSketch`]: Immutable sketch with a compact memory layout. //! +//! # Cross-language hashing +//! +//! Use [`hash::value`](crate::hash::value) wrappers to match input encodings across languages, +//! including `raw_bytes` for UTF-8 strings and byte slices. +//! +//! To match DataSketches Java, callers skip empty strings and byte slices before updates. +//! To match DataSketches C++ string updates, callers skip empty strings. +//! //! # Usage //! //! ``` diff --git a/datasketches/src/thetafamily/tuple/mod.rs b/datasketches/src/thetafamily/tuple/mod.rs index c057ee54..b9090bd8 100644 --- a/datasketches/src/thetafamily/tuple/mod.rs +++ b/datasketches/src/thetafamily/tuple/mod.rs @@ -28,6 +28,14 @@ //! summaries of shared keys through [`SummaryCombinePolicy`]; the union defaults to //! [`DefaultUnionPolicy`]. //! +//! # Cross-language hashing +//! +//! Use [`hash::value`](crate::hash::value) wrappers to match key encodings across languages, +//! including `raw_bytes` for UTF-8 strings and byte slices. +//! +//! To match DataSketches Java, callers skip empty string and byte-slice keys before updates. +//! To match DataSketches C++ string-key updates, callers skip empty string keys. +//! //! # Usage //! //! ``` diff --git a/datasketches/src/xor/mod.rs b/datasketches/src/xor/mod.rs index 3f146744..624f1c4e 100644 --- a/datasketches/src/xor/mod.rs +++ b/datasketches/src/xor/mod.rs @@ -22,14 +22,18 @@ //! //! # Cross-language hashing //! -//! Rust's [`Hash`](std::hash::Hash) may encode a value differently from other languages. Use -//! [`crate::hash::value`] to match the input encoding of another DataSketches implementation. +//! Use [`hash::value`](crate::hash::value) wrappers to match input encodings across languages, +//! including `raw_bytes` for UTF-8 strings and byte slices. //! For precomputed hashes, use the same hash function when building and querying the filter. //! //! Java hashes integer scalars as 64-bit little-endian values and strings as UTF-8 bytes with -//! xxHash64 seed `0`. Use `u64`/`i64` and [`crate::hash::value::raw_bytes`] accordingly. Java -//! skips empty strings; callers must do so explicitly here. External hashes (for example XXH3) -//! must use the precomputed-hash APIs throughout; Java's typed query API will not match them. +//! xxHash64 seed `0`. Use `u64`/`i64` and [`crate::hash::value::raw_bytes`] accordingly. External +//! hashes (for example XXH3) must use the precomputed-hash APIs throughout; Java's typed query +//! API will not match them. +//! +//! To match DataSketches Java, callers skip empty strings when building the filter and return +//! `false` for empty string membership queries. Empty byte slices are valid inputs and are not +//! filtered. //! //! # Examples //! From 3c59a5f342f8989e3225d690194aa5b293662a36 Mon Sep 17 00:00:00 2001 From: tison Date: Mon, 9 Nov 2026 17:11:26 +0800 Subject: [PATCH 3/7] docs: clarify input handling for cross-language compatibility --- datasketches/src/bloom/mod.rs | 13 ++++++++----- datasketches/src/countmin/mod.rs | 9 +++++---- datasketches/src/cpc/mod.rs | 9 +++++---- datasketches/src/hll/mod.rs | 9 +++++---- datasketches/src/thetafamily/theta/mod.rs | 9 +++++---- datasketches/src/thetafamily/tuple/mod.rs | 9 +++++---- datasketches/src/xor/mod.rs | 15 +++++++-------- 7 files changed, 40 insertions(+), 33 deletions(-) diff --git a/datasketches/src/bloom/mod.rs b/datasketches/src/bloom/mod.rs index 1486fe1a..05ba4f98 100644 --- a/datasketches/src/bloom/mod.rs +++ b/datasketches/src/bloom/mod.rs @@ -35,12 +35,15 @@ //! //! # Cross-language hashing //! -//! Use [`hash::value`](crate::hash::value) wrappers to match input encodings across languages, -//! including `raw_bytes` for UTF-8 strings and byte slices. +//! Cross-language use requires matching input encodings. See [`hash::value`](crate::hash::value) +//! for encoding helpers. //! -//! To match DataSketches Java, callers skip empty string inserts and return `false` for empty -//! string membership queries, including queries combined with insertion. Empty byte slices are -//! valid inputs and are not filtered. +//! For compatibility with DataSketches Java, skip empty string inserts and return `false` for +//! empty string membership queries, including queries combined with insertion. Pass empty byte +//! slices through to inserts and queries. +//! +//! For compatibility with DataSketches C++, skip empty string and byte-slice inserts and return +//! `false` for their membership queries, including queries combined with insertion. //! //! # Usage //! diff --git a/datasketches/src/countmin/mod.rs b/datasketches/src/countmin/mod.rs index 3a16ff47..0dcc0c41 100644 --- a/datasketches/src/countmin/mod.rs +++ b/datasketches/src/countmin/mod.rs @@ -22,11 +22,12 @@ //! //! # Cross-language hashing //! -//! For cross-language version 2 interchange, use `i64` counters and compatible input encodings: +//! Cross-language use requires matching input encodings. See [`hash::value`](crate::hash::value) +//! for encoding helpers. //! -//! * Use `i64`/`u64` for eight-byte little-endian integers and -//! [`natural_extend`](crate::hash::value::natural_extend) for narrower integers. -//! * Use [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices. +//! For version 2 interchange, use `i64` counters. Encode integers as eight little-endian bytes, +//! widening narrower integers to 64 bits first (sign-extending signed values). Encode strings as +//! UTF-8 bytes and byte slices as their contents, without length prefixes or terminators. //! //! The version 2 specification ignores empty strings and byte arrays. For cross-language use, //! callers skip these updates and return zero for empty-input estimates and both bounds. diff --git a/datasketches/src/cpc/mod.rs b/datasketches/src/cpc/mod.rs index eb4ad913..6b456a01 100644 --- a/datasketches/src/cpc/mod.rs +++ b/datasketches/src/cpc/mod.rs @@ -37,11 +37,12 @@ //! //! # Cross-language hashing //! -//! Use [`hash::value`](crate::hash::value) wrappers to match input encodings across languages, -//! including `raw_bytes` for UTF-8 strings and byte slices. +//! Cross-language use requires matching input encodings. See [`hash::value`](crate::hash::value) +//! for encoding helpers. //! -//! To match DataSketches Java, callers skip empty strings and byte slices before updates. -//! To match DataSketches C++ string updates, callers skip empty strings. +//! For compatibility with DataSketches Java, skip empty strings and byte slices before updates. +//! For compatibility with DataSketches C++, skip empty strings and pass empty byte slices through +//! to updates. mod compression; mod compression_data; diff --git a/datasketches/src/hll/mod.rs b/datasketches/src/hll/mod.rs index d9a9c6ec..6fafdcd4 100644 --- a/datasketches/src/hll/mod.rs +++ b/datasketches/src/hll/mod.rs @@ -24,11 +24,12 @@ //! //! # Cross-language hashing //! -//! Use [`hash::value`](crate::hash::value) wrappers to match input encodings across languages, -//! including `raw_bytes` for UTF-8 strings and byte slices. +//! Cross-language use requires matching input encodings. See [`hash::value`](crate::hash::value) +//! for encoding helpers. //! -//! To match DataSketches Java, callers skip empty strings and byte slices before updates. -//! To match DataSketches C++ string updates, callers skip empty strings. +//! For compatibility with DataSketches Java, skip empty strings and byte slices before updates. +//! For compatibility with DataSketches C++, skip empty strings and pass empty byte slices through +//! to updates. //! //! # Usage //! diff --git a/datasketches/src/thetafamily/theta/mod.rs b/datasketches/src/thetafamily/theta/mod.rs index 9754841b..1e25fe16 100644 --- a/datasketches/src/thetafamily/theta/mod.rs +++ b/datasketches/src/thetafamily/theta/mod.rs @@ -32,11 +32,12 @@ //! //! # Cross-language hashing //! -//! Use [`hash::value`](crate::hash::value) wrappers to match input encodings across languages, -//! including `raw_bytes` for UTF-8 strings and byte slices. +//! Cross-language use requires matching input encodings. See [`hash::value`](crate::hash::value) +//! for encoding helpers. //! -//! To match DataSketches Java, callers skip empty strings and byte slices before updates. -//! To match DataSketches C++ string updates, callers skip empty strings. +//! For compatibility with DataSketches Java, skip empty strings and byte slices before updates. +//! For compatibility with DataSketches C++, skip empty strings and pass empty byte slices through +//! to updates. //! //! # Usage //! diff --git a/datasketches/src/thetafamily/tuple/mod.rs b/datasketches/src/thetafamily/tuple/mod.rs index b9090bd8..4ba1daac 100644 --- a/datasketches/src/thetafamily/tuple/mod.rs +++ b/datasketches/src/thetafamily/tuple/mod.rs @@ -30,11 +30,12 @@ //! //! # Cross-language hashing //! -//! Use [`hash::value`](crate::hash::value) wrappers to match key encodings across languages, -//! including `raw_bytes` for UTF-8 strings and byte slices. +//! Cross-language use requires matching input encodings. See [`hash::value`](crate::hash::value) +//! for encoding helpers. //! -//! To match DataSketches Java, callers skip empty string and byte-slice keys before updates. -//! To match DataSketches C++ string-key updates, callers skip empty string keys. +//! For compatibility with DataSketches Java, skip empty string and byte-slice keys before updates. +//! For compatibility with DataSketches C++, skip empty string keys and pass empty byte-slice keys +//! through to updates. //! //! # Usage //! diff --git a/datasketches/src/xor/mod.rs b/datasketches/src/xor/mod.rs index 624f1c4e..4f047f96 100644 --- a/datasketches/src/xor/mod.rs +++ b/datasketches/src/xor/mod.rs @@ -22,18 +22,17 @@ //! //! # Cross-language hashing //! -//! Use [`hash::value`](crate::hash::value) wrappers to match input encodings across languages, -//! including `raw_bytes` for UTF-8 strings and byte slices. +//! Cross-language use requires matching input encodings. See [`hash::value`](crate::hash::value) +//! for encoding helpers. //! For precomputed hashes, use the same hash function when building and querying the filter. //! //! Java hashes integer scalars as 64-bit little-endian values and strings as UTF-8 bytes with -//! xxHash64 seed `0`. Use `u64`/`i64` and [`crate::hash::value::raw_bytes`] accordingly. External -//! hashes (for example XXH3) must use the precomputed-hash APIs throughout; Java's typed query -//! API will not match them. +//! xxHash64 seed `0`. External hashes (for example XXH3) must use the precomputed-hash APIs +//! throughout; Java's typed query API will not match them. //! -//! To match DataSketches Java, callers skip empty strings when building the filter and return -//! `false` for empty string membership queries. Empty byte slices are valid inputs and are not -//! filtered. +//! For compatibility with DataSketches Java, skip empty strings when building the filter and +//! return `false` for empty string membership queries. Pass empty byte slices through to filter +//! construction and queries. //! //! # Examples //! From 296a594c2bffa4d7eca265f88872309dec231294 Mon Sep 17 00:00:00 2001 From: tison Date: Mon, 9 Nov 2026 17:17:17 +0800 Subject: [PATCH 4/7] docs: put encoding strategy guidance in sketch modules --- datasketches/src/bloom/mod.rs | 10 ++++++++-- datasketches/src/countmin/mod.rs | 10 +++++----- datasketches/src/cpc/mod.rs | 7 +++++-- .../src/hash/value/canonical_float.rs | 2 -- datasketches/src/hash/value/mod.rs | 19 ++++++------------- datasketches/src/hash/value/natural_extend.rs | 3 --- datasketches/src/hash/value/raw_bytes.rs | 12 ++++-------- datasketches/src/hash/value/sign_extend.rs | 3 +-- datasketches/src/hll/mod.rs | 7 +++++-- datasketches/src/thetafamily/theta/mod.rs | 7 +++++-- datasketches/src/thetafamily/tuple/mod.rs | 7 +++++-- datasketches/src/xor/mod.rs | 13 +++++++------ 12 files changed, 51 insertions(+), 49 deletions(-) diff --git a/datasketches/src/bloom/mod.rs b/datasketches/src/bloom/mod.rs index 05ba4f98..aa5bcd91 100644 --- a/datasketches/src/bloom/mod.rs +++ b/datasketches/src/bloom/mod.rs @@ -35,8 +35,14 @@ //! //! # Cross-language hashing //! -//! Cross-language use requires matching input encodings. See [`hash::value`](crate::hash::value) -//! for encoding helpers. +//! For compatibility with DataSketches Java and C++, use +//! [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices. +//! Use `i64` for Java `long` inputs and `i64`/`u64` for C++ 64-bit integers. For C++ narrower +//! integer overloads, use [`natural_extend`](crate::hash::value::natural_extend). +//! +//! For C++ floating-point inputs, use [`canonical_float`](crate::hash::value::canonical_float). +//! For Java floating-point inputs, convert to `f64` and hash its bits as `u64`, preserving signed +//! zero and mapping all NaNs to `0x7ff8_0000_0000_0000`. //! //! For compatibility with DataSketches Java, skip empty string inserts and return `false` for //! empty string membership queries, including queries combined with insertion. Pass empty byte diff --git a/datasketches/src/countmin/mod.rs b/datasketches/src/countmin/mod.rs index 0dcc0c41..c8f0e95a 100644 --- a/datasketches/src/countmin/mod.rs +++ b/datasketches/src/countmin/mod.rs @@ -22,12 +22,12 @@ //! //! # Cross-language hashing //! -//! Cross-language use requires matching input encodings. See [`hash::value`](crate::hash::value) -//! for encoding helpers. +//! For version 2 interchange, use `i64` counters and the following input encodings: //! -//! For version 2 interchange, use `i64` counters. Encode integers as eight little-endian bytes, -//! widening narrower integers to 64 bits first (sign-extending signed values). Encode strings as -//! UTF-8 bytes and byte slices as their contents, without length prefixes or terminators. +//! * Use `i64`/`u64` for eight-byte little-endian integers and +//! [`natural_extend`](crate::hash::value::natural_extend) for narrower integers. +//! * Use [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices without +//! length prefixes or terminators. //! //! The version 2 specification ignores empty strings and byte arrays. For cross-language use, //! callers skip these updates and return zero for empty-input estimates and both bounds. diff --git a/datasketches/src/cpc/mod.rs b/datasketches/src/cpc/mod.rs index 6b456a01..31a90a1b 100644 --- a/datasketches/src/cpc/mod.rs +++ b/datasketches/src/cpc/mod.rs @@ -37,8 +37,11 @@ //! //! # Cross-language hashing //! -//! Cross-language use requires matching input encodings. See [`hash::value`](crate::hash::value) -//! for encoding helpers. +//! For compatibility with DataSketches Java and C++, use +//! [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices, and +//! [`canonical_float`](crate::hash::value::canonical_float) for floating-point values. +//! Use `i64` for Java `long` inputs and `i64`/`u64` for C++ 64-bit integers. For C++ narrower +//! integer overloads, use [`sign_extend`](crate::hash::value::sign_extend). //! //! For compatibility with DataSketches Java, skip empty strings and byte slices before updates. //! For compatibility with DataSketches C++, skip empty strings and pass empty byte slices through diff --git a/datasketches/src/hash/value/canonical_float.rs b/datasketches/src/hash/value/canonical_float.rs index 8b31232e..56a1e082 100644 --- a/datasketches/src/hash/value/canonical_float.rs +++ b/datasketches/src/hash/value/canonical_float.rs @@ -20,8 +20,6 @@ //! [`CanonicalFloat`] maps `f32` and `f64` values through a canonical `f64` bit pattern before //! hashing. Signed zero values hash the same, all NaN values use one canonical NaN bit pattern, //! and equal `f32`/`f64` values hash the same. -//! -//! Use this encoding to match floating-point hashing in DataSketches Java and DataSketches C++. use std::hash::Hash; use std::hash::Hasher; diff --git a/datasketches/src/hash/value/mod.rs b/datasketches/src/hash/value/mod.rs index 803aba5d..7fd3eba5 100644 --- a/datasketches/src/hash/value/mod.rs +++ b/datasketches/src/hash/value/mod.rs @@ -19,7 +19,8 @@ //! //! Sketch update APIs accept any value that implements [`Hash`]. For most Rust values, //! passing the value directly is sufficient. This module provides value wrappers for -//! cases where the default implementation does not match a sketch's compatibility rules. +//! cases where the default implementation does not match the required input encoding. See each +//! sketch's module documentation for cross-language compatibility guidance. //! //! ## Floating-point Numbers //! @@ -27,8 +28,6 @@ //! pattern before hashing. Signed zero values hash the same, all NaN values use one canonical NaN //! bit pattern, and equal `f32`/`f64` values hash the same. //! -//! Use this encoding to match floating-point hashing in DataSketches Java and DataSketches C++. -//! //! The concrete wrapper documentation provides more details and examples. //! //! * [`canonical_float::from_f32`] @@ -37,8 +36,7 @@ //! ## Integers //! //! [`sign_extend::SignExtend`] first sign-extends values to 64-bits, and then hashes the resulting -//! integers. Use this encoding to match short-integer hashing in DataSketches C++'s HLL and CPC -//! sketches. +//! integers. Unsigned values are interpreted as signed at their original width before extension. //! //! The concrete wrapper documentation provides more details and examples. //! @@ -47,8 +45,7 @@ //! * [`sign_extend::from_i32`], [`sign_extend::from_u32`] //! //! [`natural_extend::NaturalExtend`] first widens signed values to `i64` and unsigned values to -//! `u64`, and then hashes the resulting integers. Use this encoding to match short-integer hashing -//! in DataSketches C++'s Bloom filters and Count-Min sketches. +//! `u64`, and then hashes the resulting integers. //! //! The concrete wrapper documentation provides more details and examples. //! @@ -58,12 +55,8 @@ //! //! ## Raw Bytes //! -//! [`raw_bytes::RawBytes`] hashes byte and string inputs as raw bytes without Rust's slice or -//! string length prefix. -//! -//! Use this encoding to match byte and UTF-8 string hashing in DataSketches Java and -//! DataSketches C++. Their string update APIs skip empty strings; check `is_empty` before updating -//! here as well. +//! [`raw_bytes::RawBytes`] hashes byte slices as their contents and strings as UTF-8 bytes, +//! without length prefixes or terminators. //! //! The concrete wrapper documentation provides more details and examples. //! diff --git a/datasketches/src/hash/value/natural_extend.rs b/datasketches/src/hash/value/natural_extend.rs index 780116f6..6d437bde 100644 --- a/datasketches/src/hash/value/natural_extend.rs +++ b/datasketches/src/hash/value/natural_extend.rs @@ -19,9 +19,6 @@ //! //! [`NaturalExtend`] first widens signed values to `i64` and unsigned values to `u64`, and then //! hashes the resulting integers. -//! -//! Use this encoding to match short-integer hashing in DataSketches C++'s Bloom filters and -//! Count-Min sketches. use std::hash::Hash; use std::hash::Hasher; diff --git a/datasketches/src/hash/value/raw_bytes.rs b/datasketches/src/hash/value/raw_bytes.rs index a31c3978..cc6299a7 100644 --- a/datasketches/src/hash/value/raw_bytes.rs +++ b/datasketches/src/hash/value/raw_bytes.rs @@ -17,12 +17,8 @@ //! Raw byte and string hash value wrappers. //! -//! [`RawBytes`] hashes byte and string inputs as raw bytes without Rust's slice or string length -//! prefix. -//! -//! Use this encoding to match byte and UTF-8 string hashing in DataSketches Java and -//! DataSketches C++. Their string update APIs skip empty strings; check `is_empty` before updating -//! here as well. +//! [`RawBytes`] hashes byte slices as their contents and strings as UTF-8 bytes, without length +//! prefixes or terminators. use std::hash::Hasher; @@ -62,7 +58,7 @@ pub fn from_vec(v: Vec) -> RawBytes> { /// Creates a raw-byte hashable value from a string. /// -/// This hashes the UTF-8 bytes of the string without Rust's string length prefix. +/// This hashes the UTF-8 bytes of the string without a length prefix or terminator. /// /// # Examples /// @@ -106,7 +102,7 @@ pub fn from_slice(v: &[u8]) -> RawBytes<&[u8]> { /// Creates a raw-byte hashable value from a string slice. /// -/// This hashes the UTF-8 bytes of the string slice without Rust's string length prefix. +/// This hashes the UTF-8 bytes of the string slice without a length prefix or terminator. /// /// # Examples /// diff --git a/datasketches/src/hash/value/sign_extend.rs b/datasketches/src/hash/value/sign_extend.rs index eaaec9d5..5486c0a8 100644 --- a/datasketches/src/hash/value/sign_extend.rs +++ b/datasketches/src/hash/value/sign_extend.rs @@ -18,8 +18,7 @@ //! Sign-extended integer hash value wrappers. //! //! [`SignExtend`] first sign-extends values to 64-bits and then hashes the resulting integers. -//! -//! Use this encoding to match short-integer hashing in DataSketches C++'s HLL and CPC sketches. +//! Unsigned values are interpreted as signed at their original width before extension. use std::hash::Hash; use std::hash::Hasher; diff --git a/datasketches/src/hll/mod.rs b/datasketches/src/hll/mod.rs index 6fafdcd4..34842858 100644 --- a/datasketches/src/hll/mod.rs +++ b/datasketches/src/hll/mod.rs @@ -24,8 +24,11 @@ //! //! # Cross-language hashing //! -//! Cross-language use requires matching input encodings. See [`hash::value`](crate::hash::value) -//! for encoding helpers. +//! For compatibility with DataSketches Java and C++, use +//! [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices, and +//! [`canonical_float`](crate::hash::value::canonical_float) for floating-point values. +//! Use `i64` for Java `long` inputs and `i64`/`u64` for C++ 64-bit integers. For C++ narrower +//! integer overloads, use [`sign_extend`](crate::hash::value::sign_extend). //! //! For compatibility with DataSketches Java, skip empty strings and byte slices before updates. //! For compatibility with DataSketches C++, skip empty strings and pass empty byte slices through diff --git a/datasketches/src/thetafamily/theta/mod.rs b/datasketches/src/thetafamily/theta/mod.rs index 1e25fe16..ceff8f43 100644 --- a/datasketches/src/thetafamily/theta/mod.rs +++ b/datasketches/src/thetafamily/theta/mod.rs @@ -32,8 +32,11 @@ //! //! # Cross-language hashing //! -//! Cross-language use requires matching input encodings. See [`hash::value`](crate::hash::value) -//! for encoding helpers. +//! For compatibility with DataSketches Java and C++, use +//! [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices, and +//! [`canonical_float`](crate::hash::value::canonical_float) for floating-point values. +//! Use `i64` for Java `long` inputs and `i64`/`u64` for C++ 64-bit integers. For C++ narrower +//! integer overloads, use [`sign_extend`](crate::hash::value::sign_extend). //! //! For compatibility with DataSketches Java, skip empty strings and byte slices before updates. //! For compatibility with DataSketches C++, skip empty strings and pass empty byte slices through diff --git a/datasketches/src/thetafamily/tuple/mod.rs b/datasketches/src/thetafamily/tuple/mod.rs index 4ba1daac..bab52594 100644 --- a/datasketches/src/thetafamily/tuple/mod.rs +++ b/datasketches/src/thetafamily/tuple/mod.rs @@ -30,8 +30,11 @@ //! //! # Cross-language hashing //! -//! Cross-language use requires matching input encodings. See [`hash::value`](crate::hash::value) -//! for encoding helpers. +//! For compatibility with DataSketches Java and C++, use +//! [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices, and +//! [`canonical_float`](crate::hash::value::canonical_float) for floating-point keys. +//! Use `i64` for Java `long` inputs and `i64`/`u64` for C++ 64-bit integers. For C++ narrower +//! integer overloads, use [`sign_extend`](crate::hash::value::sign_extend). //! //! For compatibility with DataSketches Java, skip empty string and byte-slice keys before updates. //! For compatibility with DataSketches C++, skip empty string keys and pass empty byte-slice keys diff --git a/datasketches/src/xor/mod.rs b/datasketches/src/xor/mod.rs index 4f047f96..f05191e7 100644 --- a/datasketches/src/xor/mod.rs +++ b/datasketches/src/xor/mod.rs @@ -22,13 +22,14 @@ //! //! # Cross-language hashing //! -//! Cross-language use requires matching input encodings. See [`hash::value`](crate::hash::value) -//! for encoding helpers. -//! For precomputed hashes, use the same hash function when building and querying the filter. +//! For compatibility with DataSketches Java, use `i64` for `long` inputs and +//! [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices. For +//! floating-point inputs, convert to `f64` and hash its bits as `u64`, preserving signed zero and +//! mapping all NaNs to `0x7ff8_0000_0000_0000`. Java hashes these encodings with xxHash64 seed `0`. //! -//! Java hashes integer scalars as 64-bit little-endian values and strings as UTF-8 bytes with -//! xxHash64 seed `0`. External hashes (for example XXH3) must use the precomputed-hash APIs -//! throughout; Java's typed query API will not match them. +//! For precomputed hashes, use the same hash function when building and querying the filter. +//! External hashes (for example XXH3) must use the precomputed-hash APIs throughout; Java's typed +//! query API will not match them. //! //! For compatibility with DataSketches Java, skip empty strings when building the filter and //! return `false` for empty string membership queries. Pass empty byte slices through to filter From 28d31f8808eff5e4991614133bc986a230f014ae Mon Sep 17 00:00:00 2001 From: tison Date: Mon, 9 Nov 2026 19:01:47 +0800 Subject: [PATCH 5/7] docs: defer Java filter floating-point compatibility guidance --- datasketches/src/bloom/mod.rs | 2 -- datasketches/src/xor/mod.rs | 5 ++--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/datasketches/src/bloom/mod.rs b/datasketches/src/bloom/mod.rs index aa5bcd91..88ae6563 100644 --- a/datasketches/src/bloom/mod.rs +++ b/datasketches/src/bloom/mod.rs @@ -41,8 +41,6 @@ //! integer overloads, use [`natural_extend`](crate::hash::value::natural_extend). //! //! For C++ floating-point inputs, use [`canonical_float`](crate::hash::value::canonical_float). -//! For Java floating-point inputs, convert to `f64` and hash its bits as `u64`, preserving signed -//! zero and mapping all NaNs to `0x7ff8_0000_0000_0000`. //! //! For compatibility with DataSketches Java, skip empty string inserts and return `false` for //! empty string membership queries, including queries combined with insertion. Pass empty byte diff --git a/datasketches/src/xor/mod.rs b/datasketches/src/xor/mod.rs index f05191e7..27b01c73 100644 --- a/datasketches/src/xor/mod.rs +++ b/datasketches/src/xor/mod.rs @@ -23,9 +23,8 @@ //! # Cross-language hashing //! //! For compatibility with DataSketches Java, use `i64` for `long` inputs and -//! [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices. For -//! floating-point inputs, convert to `f64` and hash its bits as `u64`, preserving signed zero and -//! mapping all NaNs to `0x7ff8_0000_0000_0000`. Java hashes these encodings with xxHash64 seed `0`. +//! [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices. +//! Java hashes these encodings with xxHash64 seed `0`. //! //! For precomputed hashes, use the same hash function when building and querying the filter. //! External hashes (for example XXH3) must use the precomputed-hash APIs throughout; Java's typed From 9b6ab7937a787bcdd527701ed4bfe6849968b738 Mon Sep 17 00:00:00 2001 From: tison Date: Mon, 9 Nov 2026 19:16:55 +0800 Subject: [PATCH 6/7] docs: unify cross-language input conventions and navigation --- datasketches/src/bloom/mod.rs | 18 +++---- datasketches/src/bloom/sketch.rs | 3 ++ datasketches/src/countmin/mod.rs | 14 ++--- datasketches/src/countmin/sketch.rs | 6 --- datasketches/src/cpc/mod.rs | 15 +++--- datasketches/src/cpc/sketch.rs | 6 +-- .../src/hash/value/canonical_float.rs | 3 +- datasketches/src/hash/value/mod.rs | 53 ++++--------------- datasketches/src/hash/value/natural_extend.rs | 3 +- datasketches/src/hash/value/raw_bytes.rs | 2 +- datasketches/src/hash/value/sign_extend.rs | 2 +- datasketches/src/hll/mod.rs | 21 ++++---- datasketches/src/hll/sketch.rs | 6 +-- datasketches/src/thetafamily/theta/mod.rs | 15 +++--- datasketches/src/thetafamily/theta/sketch.rs | 6 +-- datasketches/src/thetafamily/tuple/mod.rs | 15 +++--- datasketches/src/thetafamily/tuple/sketch.rs | 3 ++ datasketches/src/xor/filter.rs | 6 +++ datasketches/src/xor/mod.rs | 19 +++---- 19 files changed, 91 insertions(+), 125 deletions(-) diff --git a/datasketches/src/bloom/mod.rs b/datasketches/src/bloom/mod.rs index 88ae6563..38c8efee 100644 --- a/datasketches/src/bloom/mod.rs +++ b/datasketches/src/bloom/mod.rs @@ -35,19 +35,15 @@ //! //! # Cross-language hashing //! -//! For compatibility with DataSketches Java and C++, use -//! [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices. -//! Use `i64` for Java `long` inputs and `i64`/`u64` for C++ 64-bit integers. For C++ narrower -//! integer overloads, use [`natural_extend`](crate::hash::value::natural_extend). +//! For cross-language use, apply the following input conventions: //! -//! For C++ floating-point inputs, use [`canonical_float`](crate::hash::value::canonical_float). +//! * Use `i64`/`u64` for 64-bit integers and [`natural_extend`](crate::hash::value::natural_extend) +//! for narrower integers. +//! * Use [`canonical_float`](crate::hash::value::canonical_float) for floating-point values. +//! * Use [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices. //! -//! For compatibility with DataSketches Java, skip empty string inserts and return `false` for -//! empty string membership queries, including queries combined with insertion. Pass empty byte -//! slices through to inserts and queries. -//! -//! For compatibility with DataSketches C++, skip empty string and byte-slice inserts and return -//! `false` for their membership queries, including queries combined with insertion. +//! Callers skip empty string and byte-slice inserts and return `false` for their membership +//! queries, including queries combined with insertion. //! //! # Usage //! diff --git a/datasketches/src/bloom/sketch.rs b/datasketches/src/bloom/sketch.rs index 4dce8ab2..c9e21a15 100644 --- a/datasketches/src/bloom/sketch.rs +++ b/datasketches/src/bloom/sketch.rs @@ -38,6 +38,9 @@ const EMPTY_FLAG_MASK: u8 = 1 << 2; /// * No false negatives (inserted items always return `true`) /// * Tunable false positive rate /// * Constant space usage +/// +/// For input encodings and empty-input handling, see +/// [Cross-language hashing](crate::bloom#cross-language-hashing). #[derive(Debug, Clone, PartialEq)] pub struct BloomFilter { /// Hash seed for all hash functions diff --git a/datasketches/src/countmin/mod.rs b/datasketches/src/countmin/mod.rs index c8f0e95a..7c810282 100644 --- a/datasketches/src/countmin/mod.rs +++ b/datasketches/src/countmin/mod.rs @@ -22,15 +22,15 @@ //! //! # Cross-language hashing //! -//! For version 2 interchange, use `i64` counters and the following input encodings: +//! For cross-language use, apply the following input conventions: //! -//! * Use `i64`/`u64` for eight-byte little-endian integers and -//! [`natural_extend`](crate::hash::value::natural_extend) for narrower integers. -//! * Use [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices without -//! length prefixes or terminators. +//! * Use `i64`/`u64` for 64-bit integers and [`natural_extend`](crate::hash::value::natural_extend) +//! for narrower integers. +//! * Use [`canonical_float`](crate::hash::value::canonical_float) for floating-point values. +//! * Use [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices. //! -//! The version 2 specification ignores empty strings and byte arrays. For cross-language use, -//! callers skip these updates and return zero for empty-input estimates and both bounds. +//! Version 2 interchange requires `i64` counters. Callers skip empty string and byte-slice +//! updates and return zero for their estimates and both bounds. //! //! # Usage //! diff --git a/datasketches/src/countmin/sketch.rs b/datasketches/src/countmin/sketch.rs index 350f9bc9..27d50b29 100644 --- a/datasketches/src/countmin/sketch.rs +++ b/datasketches/src/countmin/sketch.rs @@ -317,9 +317,6 @@ impl CountMinSketch { /// Updates the sketch with a single occurrence of the item. /// - /// Use [`hash::value`](crate::hash::value) wrappers to select an input encoding for - /// cross-language hashing. - /// /// # Panics /// /// Panics without modifying the sketch if the total absolute weight would exceed `T::MAX`. @@ -339,9 +336,6 @@ impl CountMinSketch { /// Updates the sketch with the given item and weight. /// - /// Use [`hash::value`](crate::hash::value) wrappers to select an input encoding for - /// cross-language hashing. - /// /// # Panics /// /// Panics without modifying the sketch if the absolute weight or the total absolute weight diff --git a/datasketches/src/cpc/mod.rs b/datasketches/src/cpc/mod.rs index 31a90a1b..6d2198ab 100644 --- a/datasketches/src/cpc/mod.rs +++ b/datasketches/src/cpc/mod.rs @@ -37,15 +37,14 @@ //! //! # Cross-language hashing //! -//! For compatibility with DataSketches Java and C++, use -//! [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices, and -//! [`canonical_float`](crate::hash::value::canonical_float) for floating-point values. -//! Use `i64` for Java `long` inputs and `i64`/`u64` for C++ 64-bit integers. For C++ narrower -//! integer overloads, use [`sign_extend`](crate::hash::value::sign_extend). +//! For cross-language use, apply the following input conventions: //! -//! For compatibility with DataSketches Java, skip empty strings and byte slices before updates. -//! For compatibility with DataSketches C++, skip empty strings and pass empty byte slices through -//! to updates. +//! * Use `i64`/`u64` for 64-bit integers and [`sign_extend`](crate::hash::value::sign_extend) for +//! narrower integers. +//! * Use [`canonical_float`](crate::hash::value::canonical_float) for floating-point values. +//! * Use [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices. +//! +//! Callers skip empty strings and byte slices before updates. mod compression; mod compression_data; diff --git a/datasketches/src/cpc/sketch.rs b/datasketches/src/cpc/sketch.rs index d4f688a2..5ca258b7 100644 --- a/datasketches/src/cpc/sketch.rs +++ b/datasketches/src/cpc/sketch.rs @@ -59,7 +59,8 @@ use crate::hash::compute_seed_hash; /// A Compressed Probabilistic Counting sketch. /// -/// See the [module level documentation](super) for more. +/// For input encodings and empty-input handling, see +/// [Cross-language hashing](crate::cpc#cross-language-hashing). #[derive(Clone)] pub struct CpcSketch { // immutable config variables @@ -179,9 +180,6 @@ impl CpcSketch { /// Updates the sketch with a hashable value. /// - /// Use [`hash::value`](crate::hash::value) wrappers to select an input encoding for - /// cross-language hashing. - /// /// # Examples /// /// ```rust diff --git a/datasketches/src/hash/value/canonical_float.rs b/datasketches/src/hash/value/canonical_float.rs index 56a1e082..7b9acd5f 100644 --- a/datasketches/src/hash/value/canonical_float.rs +++ b/datasketches/src/hash/value/canonical_float.rs @@ -29,7 +29,8 @@ use crate::hash::value::Value; /// A floating-point value wrapper that uses canonical floating-point hashing. /// -/// See the [module level documentation](super) for more. +/// See the [canonical_float](crate::hash::value::canonical_float) module for encoding details and +/// examples. pub type CanonicalFloat = Value; /// Hashing strategy for [`CanonicalFloat`]. diff --git a/datasketches/src/hash/value/mod.rs b/datasketches/src/hash/value/mod.rs index 7fd3eba5..e84df554 100644 --- a/datasketches/src/hash/value/mod.rs +++ b/datasketches/src/hash/value/mod.rs @@ -19,51 +19,20 @@ //! //! Sketch update APIs accept any value that implements [`Hash`]. For most Rust values, //! passing the value directly is sufficient. This module provides value wrappers for -//! cases where the default implementation does not match the required input encoding. See each -//! sketch's module documentation for cross-language compatibility guidance. +//! cases where the default implementation does not match the required input encoding. //! -//! ## Floating-point Numbers +//! ## Encoding strategies //! -//! [`canonical_float::CanonicalFloat`] maps `f32` and `f64` values through a canonical `f64` bit -//! pattern before hashing. Signed zero values hash the same, all NaN values use one canonical NaN -//! bit pattern, and equal `f32`/`f64` values hash the same. +//! * [`canonical_float`] widens floating-point values to `f64`, normalizes signed zero to `+0.0`, +//! and maps all NaNs to one bit pattern before hashing. +//! * [`sign_extend`] interprets integers as signed at their original width and sign-extends them to +//! 64 bits before hashing. +//! * [`natural_extend`] widens signed integers to `i64` and unsigned integers to `u64` before +//! hashing. +//! * [`raw_bytes`] hashes byte slices as their contents and strings as UTF-8 bytes, without length +//! prefixes or terminators. //! -//! The concrete wrapper documentation provides more details and examples. -//! -//! * [`canonical_float::from_f32`] -//! * [`canonical_float::from_f64`] -//! -//! ## Integers -//! -//! [`sign_extend::SignExtend`] first sign-extends values to 64-bits, and then hashes the resulting -//! integers. Unsigned values are interpreted as signed at their original width before extension. -//! -//! The concrete wrapper documentation provides more details and examples. -//! -//! * [`sign_extend::from_i8`], [`sign_extend::from_u8`] -//! * [`sign_extend::from_i16`], [`sign_extend::from_u16`] -//! * [`sign_extend::from_i32`], [`sign_extend::from_u32`] -//! -//! [`natural_extend::NaturalExtend`] first widens signed values to `i64` and unsigned values to -//! `u64`, and then hashes the resulting integers. -//! -//! The concrete wrapper documentation provides more details and examples. -//! -//! * [`natural_extend::from_i8`], [`natural_extend::from_u8`] -//! * [`natural_extend::from_i16`], [`natural_extend::from_u16`] -//! * [`natural_extend::from_i32`], [`natural_extend::from_u32`] -//! -//! ## Raw Bytes -//! -//! [`raw_bytes::RawBytes`] hashes byte slices as their contents and strings as UTF-8 bytes, -//! without length prefixes or terminators. -//! -//! The concrete wrapper documentation provides more details and examples. -//! -//! * [`raw_bytes::from_vec`] -//! * [`raw_bytes::from_string`] -//! * [`raw_bytes::from_slice`] -//! * [`raw_bytes::from_str`] +//! Each strategy module provides constructors and examples. pub mod canonical_float; pub mod natural_extend; diff --git a/datasketches/src/hash/value/natural_extend.rs b/datasketches/src/hash/value/natural_extend.rs index 6d437bde..c240d8b2 100644 --- a/datasketches/src/hash/value/natural_extend.rs +++ b/datasketches/src/hash/value/natural_extend.rs @@ -28,7 +28,8 @@ use crate::hash::value::Value; /// An integer value wrapper that uses Rust's natural integer widening before hashing. /// -/// See the [module level documentation](super) for more. +/// See the [natural_extend](crate::hash::value::natural_extend) module for encoding details and +/// examples. pub type NaturalExtend = Value; /// Hashing strategy for [`NaturalExtend`]. diff --git a/datasketches/src/hash/value/raw_bytes.rs b/datasketches/src/hash/value/raw_bytes.rs index cc6299a7..1ec2154f 100644 --- a/datasketches/src/hash/value/raw_bytes.rs +++ b/datasketches/src/hash/value/raw_bytes.rs @@ -27,7 +27,7 @@ use crate::hash::value::Value; /// A byte or string value wrapper that hashes raw bytes. /// -/// See the [module level documentation](super) for more. +/// See the [raw_bytes](crate::hash::value::raw_bytes) module for encoding details and examples. pub type RawBytes = Value; /// Hashing strategy for [`RawBytes`]. diff --git a/datasketches/src/hash/value/sign_extend.rs b/datasketches/src/hash/value/sign_extend.rs index 5486c0a8..c8e4c1a9 100644 --- a/datasketches/src/hash/value/sign_extend.rs +++ b/datasketches/src/hash/value/sign_extend.rs @@ -28,7 +28,7 @@ use crate::hash::value::Value; /// An integer value wrapper that sign-extends the value before hashing. /// -/// See the [module level documentation](super) for more. +/// See the [sign_extend](crate::hash::value::sign_extend) module for encoding details and examples. pub type SignExtend = Value; /// Hashing strategy for [`SignExtend`]. diff --git a/datasketches/src/hll/mod.rs b/datasketches/src/hll/mod.rs index 34842858..758f67f0 100644 --- a/datasketches/src/hll/mod.rs +++ b/datasketches/src/hll/mod.rs @@ -24,15 +24,14 @@ //! //! # Cross-language hashing //! -//! For compatibility with DataSketches Java and C++, use -//! [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices, and -//! [`canonical_float`](crate::hash::value::canonical_float) for floating-point values. -//! Use `i64` for Java `long` inputs and `i64`/`u64` for C++ 64-bit integers. For C++ narrower -//! integer overloads, use [`sign_extend`](crate::hash::value::sign_extend). +//! For cross-language use, apply the following input conventions: //! -//! For compatibility with DataSketches Java, skip empty strings and byte slices before updates. -//! For compatibility with DataSketches C++, skip empty strings and pass empty byte slices through -//! to updates. +//! * Use `i64`/`u64` for 64-bit integers and [`sign_extend`](crate::hash::value::sign_extend) for +//! narrower integers. +//! * Use [`canonical_float`](crate::hash::value::canonical_float) for floating-point values. +//! * Use [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices. +//! +//! Callers skip empty strings and byte slices before updates. //! //! # Usage //! @@ -123,6 +122,9 @@ const RESIZE_DENOMINATOR: u32 = 4; /// Compute a coupon once with [`Coupon::from_value`] and pass it to /// [`HllSketch::update_with_coupon`] on sketches with any `lg_k` or [`HllType`]. /// +/// For input encodings and empty-input handling, see +/// [Cross-language hashing](crate::hll#cross-language-hashing). +/// /// # Examples /// /// ``` @@ -159,9 +161,6 @@ impl Coupon { /// Computes the HLL coupon for a hashable value. /// - /// Use [`hash::value`](crate::hash::value) wrappers to select an input encoding for - /// cross-language hashing. - /// /// # Examples /// /// ``` diff --git a/datasketches/src/hll/sketch.rs b/datasketches/src/hll/sketch.rs index 910a730c..a0651a17 100644 --- a/datasketches/src/hll/sketch.rs +++ b/datasketches/src/hll/sketch.rs @@ -55,7 +55,8 @@ use crate::hll::serialization::extract_tgt_hll_type; /// A HyperLogLog sketch. /// -/// See the [module level documentation](super) for more. +/// For input encodings and empty-input handling, see +/// [Cross-language hashing](crate::hll#cross-language-hashing). #[derive(Clone, PartialEq)] pub struct HllSketch { lg_config_k: u8, @@ -137,9 +138,6 @@ impl HllSketch { /// Updates the sketch with a value. /// - /// Use [`hash::value`](crate::hash::value) wrappers to select an input encoding for - /// cross-language hashing. - /// /// To reuse the hash across sketches, see [`Coupon`] and /// [`update_with_coupon`](Self::update_with_coupon). /// diff --git a/datasketches/src/thetafamily/theta/mod.rs b/datasketches/src/thetafamily/theta/mod.rs index ceff8f43..0f5dd0d1 100644 --- a/datasketches/src/thetafamily/theta/mod.rs +++ b/datasketches/src/thetafamily/theta/mod.rs @@ -32,15 +32,14 @@ //! //! # Cross-language hashing //! -//! For compatibility with DataSketches Java and C++, use -//! [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices, and -//! [`canonical_float`](crate::hash::value::canonical_float) for floating-point values. -//! Use `i64` for Java `long` inputs and `i64`/`u64` for C++ 64-bit integers. For C++ narrower -//! integer overloads, use [`sign_extend`](crate::hash::value::sign_extend). +//! For cross-language use, apply the following input conventions: //! -//! For compatibility with DataSketches Java, skip empty strings and byte slices before updates. -//! For compatibility with DataSketches C++, skip empty strings and pass empty byte slices through -//! to updates. +//! * Use `i64`/`u64` for 64-bit integers and [`sign_extend`](crate::hash::value::sign_extend) for +//! narrower integers. +//! * Use [`canonical_float`](crate::hash::value::canonical_float) for floating-point values. +//! * Use [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices. +//! +//! Callers skip empty strings and byte slices before updates. //! //! # Usage //! diff --git a/datasketches/src/thetafamily/theta/sketch.rs b/datasketches/src/thetafamily/theta/sketch.rs index 4ec71b79..e9c7579b 100644 --- a/datasketches/src/thetafamily/theta/sketch.rs +++ b/datasketches/src/thetafamily/theta/sketch.rs @@ -203,6 +203,9 @@ impl<'a> From<&'a CompactThetaSketch> for ThetaSketchView<'a> { } /// Mutable theta sketch for building from input data. +/// +/// For input encodings and empty-input handling, see +/// [Cross-language hashing](crate::theta#cross-language-hashing). #[derive(Debug)] pub struct ThetaSketch { table: ThetaHashTable, @@ -218,9 +221,6 @@ impl ThetaSketch { /// Updates the sketch with a hashable value. /// - /// Use [`hash::value`](crate::hash::value) wrappers to select an input encoding for - /// cross-language hashing. - /// /// # Examples /// /// ``` diff --git a/datasketches/src/thetafamily/tuple/mod.rs b/datasketches/src/thetafamily/tuple/mod.rs index bab52594..bc12cc39 100644 --- a/datasketches/src/thetafamily/tuple/mod.rs +++ b/datasketches/src/thetafamily/tuple/mod.rs @@ -30,15 +30,14 @@ //! //! # Cross-language hashing //! -//! For compatibility with DataSketches Java and C++, use -//! [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices, and -//! [`canonical_float`](crate::hash::value::canonical_float) for floating-point keys. -//! Use `i64` for Java `long` inputs and `i64`/`u64` for C++ 64-bit integers. For C++ narrower -//! integer overloads, use [`sign_extend`](crate::hash::value::sign_extend). +//! For cross-language use, apply the following input conventions: //! -//! For compatibility with DataSketches Java, skip empty string and byte-slice keys before updates. -//! For compatibility with DataSketches C++, skip empty string keys and pass empty byte-slice keys -//! through to updates. +//! * Use `i64`/`u64` for 64-bit integers and [`sign_extend`](crate::hash::value::sign_extend) for +//! narrower integers. +//! * Use [`canonical_float`](crate::hash::value::canonical_float) for floating-point values. +//! * Use [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices. +//! +//! These encodings apply to keys. Callers skip empty string and byte-slice keys before updates. //! //! # Usage //! diff --git a/datasketches/src/thetafamily/tuple/sketch.rs b/datasketches/src/thetafamily/tuple/sketch.rs index 0fee8218..901a646a 100644 --- a/datasketches/src/thetafamily/tuple/sketch.rs +++ b/datasketches/src/thetafamily/tuple/sketch.rs @@ -245,6 +245,9 @@ impl<'a, S> From<&'a CompactTupleSketch> for TupleSketchView<'a, S> { /// [`P::Summary`](SummaryPolicy::Summary), while each accepted update type is selected by a /// [`SummaryUpdatePolicy`] implementation. /// +/// For input encodings and empty-input handling, see +/// [Cross-language hashing](crate::tuple#cross-language-hashing). +/// /// # Examples /// /// ``` diff --git a/datasketches/src/xor/filter.rs b/datasketches/src/xor/filter.rs index b378c8ae..e6acd955 100644 --- a/datasketches/src/xor/filter.rs +++ b/datasketches/src/xor/filter.rs @@ -101,6 +101,9 @@ impl Fingerprints { /// /// Query values with [`XorFilter::contains`] and precomputed hashes with /// [`XorFilter::contains_hash`]. +/// +/// For input encodings and empty-input handling, see +/// [Cross-language hashing](crate::xor#cross-language-hashing). #[derive(Debug)] pub struct XorFilterBuilder { filter_type: XorFilterType, @@ -161,6 +164,9 @@ impl XorFilterBuilder { /// `true` may be a false positive, with probability determined by [`XorFilterType`], even for an /// empty input set. Values cannot be added after construction; rebuild the filter when the set /// changes. +/// +/// For input encodings and empty-input handling, see +/// [Cross-language hashing](crate::xor#cross-language-hashing). #[derive(Debug, Clone, PartialEq, Eq)] pub struct XorFilter { // Cache the derived length to avoid division on every query. diff --git a/datasketches/src/xor/mod.rs b/datasketches/src/xor/mod.rs index 27b01c73..bc6f6a5d 100644 --- a/datasketches/src/xor/mod.rs +++ b/datasketches/src/xor/mod.rs @@ -22,17 +22,18 @@ //! //! # Cross-language hashing //! -//! For compatibility with DataSketches Java, use `i64` for `long` inputs and -//! [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices. -//! Java hashes these encodings with xxHash64 seed `0`. +//! For cross-language use, apply the following input conventions: //! -//! For precomputed hashes, use the same hash function when building and querying the filter. -//! External hashes (for example XXH3) must use the precomputed-hash APIs throughout; Java's typed -//! query API will not match them. +//! * Use `i64`/`u64` for 64-bit integers and [`natural_extend`](crate::hash::value::natural_extend) +//! for narrower integers. +//! * Use [`canonical_float`](crate::hash::value::canonical_float) for floating-point values. +//! * Use [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices. //! -//! For compatibility with DataSketches Java, skip empty strings when building the filter and -//! return `false` for empty string membership queries. Pass empty byte slices through to filter -//! construction and queries. +//! Callers skip empty strings and byte slices when building the filter and return `false` for +//! their membership queries. +//! +//! Value-based APIs use xxHash64 with seed `0`. For precomputed hashes, use the same hash function +//! when building and querying the filter, and use the precomputed-hash APIs throughout. //! //! # Examples //! From 65d10163affe015b616877c478b0757680990073 Mon Sep 17 00:00:00 2001 From: tison Date: Mon, 9 Nov 2026 20:59:51 +0800 Subject: [PATCH 7/7] docs: clarify caller responsibilities and Count-Min usage --- datasketches/src/bloom/mod.rs | 4 +-- datasketches/src/bloom/sketch.rs | 3 +- datasketches/src/countmin/mod.rs | 36 ++++++++++++------- datasketches/src/countmin/sketch.rs | 30 +++++++--------- datasketches/src/cpc/mod.rs | 2 +- datasketches/src/cpc/sketch.rs | 3 +- .../src/hash/value/canonical_float.rs | 3 +- datasketches/src/hash/value/natural_extend.rs | 3 +- datasketches/src/hash/value/raw_bytes.rs | 2 +- datasketches/src/hash/value/sign_extend.rs | 2 +- datasketches/src/hll/mod.rs | 5 ++- datasketches/src/hll/sketch.rs | 3 +- datasketches/src/thetafamily/theta/mod.rs | 2 +- datasketches/src/thetafamily/theta/sketch.rs | 3 +- datasketches/src/thetafamily/tuple/mod.rs | 2 +- datasketches/src/thetafamily/tuple/sketch.rs | 3 +- datasketches/src/xor/filter.rs | 6 ++-- datasketches/src/xor/mod.rs | 4 +-- 18 files changed, 55 insertions(+), 61 deletions(-) diff --git a/datasketches/src/bloom/mod.rs b/datasketches/src/bloom/mod.rs index 38c8efee..e5d67652 100644 --- a/datasketches/src/bloom/mod.rs +++ b/datasketches/src/bloom/mod.rs @@ -42,8 +42,8 @@ //! * Use [`canonical_float`](crate::hash::value::canonical_float) for floating-point values. //! * Use [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices. //! -//! Callers skip empty string and byte-slice inserts and return `false` for their membership -//! queries, including queries combined with insertion. +//! Skip empty strings and byte slices before inserting into the filter. For these inputs, +//! return `false` without querying the filter, including for queries combined with insertion. //! //! # Usage //! diff --git a/datasketches/src/bloom/sketch.rs b/datasketches/src/bloom/sketch.rs index c9e21a15..b6dfbe19 100644 --- a/datasketches/src/bloom/sketch.rs +++ b/datasketches/src/bloom/sketch.rs @@ -39,8 +39,7 @@ const EMPTY_FLAG_MASK: u8 = 1 << 2; /// * Tunable false positive rate /// * Constant space usage /// -/// For input encodings and empty-input handling, see -/// [Cross-language hashing](crate::bloom#cross-language-hashing). +/// See the [module level documentation](super) for more. #[derive(Debug, Clone, PartialEq)] pub struct BloomFilter { /// Hash seed for all hash functions diff --git a/datasketches/src/countmin/mod.rs b/datasketches/src/countmin/mod.rs index 7c810282..14855a15 100644 --- a/datasketches/src/countmin/mod.rs +++ b/datasketches/src/countmin/mod.rs @@ -29,11 +29,32 @@ //! * Use [`canonical_float`](crate::hash::value::canonical_float) for floating-point values. //! * Use [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices. //! -//! Version 2 interchange requires `i64` counters. Callers skip empty string and byte-slice -//! updates and return zero for their estimates and both bounds. +//! Use `i64` counters for cross-language interchange. Skip empty strings and byte slices before +//! updating the sketch. For these inputs, return zero for the estimate and both bounds without +//! querying the sketch. //! //! # Usage //! +//! Choose the number of buckets and hash functions from the desired relative error and +//! confidence, then update the sketch as items arrive: +//! +//! ``` +//! use datasketches::countmin::CountMinSketch; +//! +//! let buckets = CountMinSketch::::suggest_num_buckets(0.01)?; +//! let hashes = CountMinSketch::::suggest_num_hashes(0.99)?; +//! let mut sketch = CountMinSketch::::new(hashes, buckets)?; +//! sketch.update(42i64); +//! sketch.update_with_weight(42i64, 5); +//! +//! assert_eq!(sketch.estimate(42i64), 6); +//! assert!(sketch.lower_bound(42i64) <= 6); +//! assert!(sketch.upper_bound(42i64) >= 6); +//! # Ok::<(), datasketches::error::Error>(()) +//! ``` +//! +//! ## Empty inputs +//! //! This example handles empty strings before updating or querying. Byte slices use the same //! `is_empty()` checks with `raw_bytes::from_slice`. //! @@ -64,17 +85,6 @@ //! assert_eq!((estimate, lower, upper), (0, 0, 0)); //! # Ok::<(), datasketches::error::Error>(()) //! ``` -//! -//! # Configuration Helpers -//! -//! ``` -//! use datasketches::countmin::CountMinSketch; -//! -//! let buckets = CountMinSketch::::suggest_num_buckets(0.01).unwrap(); -//! let hashes = CountMinSketch::::suggest_num_hashes(0.99).unwrap(); -//! let sketch = CountMinSketch::::new(hashes, buckets).unwrap(); -//! assert_eq!(sketch.estimate(1i64), 0); -//! ``` mod sketch; pub use self::sketch::CountMinSketch; diff --git a/datasketches/src/countmin/sketch.rs b/datasketches/src/countmin/sketch.rs index 27d50b29..88bf2876 100644 --- a/datasketches/src/countmin/sketch.rs +++ b/datasketches/src/countmin/sketch.rs @@ -45,11 +45,7 @@ const MAX_TABLE_ENTRIES: usize = 1 << 30; /// The sketch provides upper and lower bounds on estimated item frequencies /// with configurable relative error and confidence. /// -/// New sketches use serial version 2. Deserialized version 1 sketches retain their legacy -/// hashing and serialization format, and sketches of different versions cannot be merged. -/// -/// For input encodings and empty-input handling, see -/// [Cross-language hashing](crate::countmin#cross-language-hashing). +/// See the [module level documentation](super) for more. #[derive(Debug, Clone, PartialEq)] pub struct CountMinSketch { num_hashes: u8, @@ -443,11 +439,7 @@ impl CountMinSketch { /// Serializes this sketch into the Count-Min binary format. /// - /// New sketches are written as version 2. A sketch deserialized from a version 1 image - /// retains its legacy hashing for queries and updates and is written back as version 1. - /// - /// Version 1 images are not portable across implementations. Version 2 supports cross-language - /// interchange with `i64` counters and the input encodings documented on [`CountMinSketch`]. + /// A sketch restored by [`deserialize`](Self::deserialize) retains its original format. /// /// # Examples /// @@ -498,13 +490,15 @@ impl CountMinSketch { /// Deserializes a sketch from bytes using the default seed. /// - /// Accepts versions 1 and 2, preserving the image's hashing and serialization version. - /// Counter values must fit `T`. See [`CountMinSketch`] for input encodings and compatibility. + /// Accepts the current format and legacy version 1 images. Legacy images retain their original + /// hashing and serialization format and cannot be merged with newly created sketches. Use the + /// same input encodings that were used to create the image; version 1 images are not portable + /// across implementations. Counter values must fit `T`. /// /// # Errors /// - /// Returns `InvalidData` if the image is malformed or its seed hash does not match the default - /// seed. + /// Returns `InvalidData` if the image is malformed, its serialization version is unsupported, + /// or its seed hash does not match the default seed. /// /// # Examples /// @@ -523,13 +517,13 @@ impl CountMinSketch { /// Deserializes a sketch from bytes using the provided seed. /// - /// Accepts versions 1 and 2, preserving the image's hashing and serialization version. - /// Counter values must fit `T`. See [`CountMinSketch`] for input encodings and compatibility. + /// The format and counter requirements are the same as for [`deserialize`](Self::deserialize). /// /// # Errors /// - /// Returns `InvalidData` if the image is malformed, its seed hash does not match `seed`, or - /// `seed` itself computes to the reserved zero seed hash. + /// Returns `InvalidData` if the image is malformed, its serialization version is unsupported, + /// its seed hash does not match `seed`, or `seed` itself computes to the reserved zero seed + /// hash. /// /// # Examples /// diff --git a/datasketches/src/cpc/mod.rs b/datasketches/src/cpc/mod.rs index 6d2198ab..10c81b39 100644 --- a/datasketches/src/cpc/mod.rs +++ b/datasketches/src/cpc/mod.rs @@ -44,7 +44,7 @@ //! * Use [`canonical_float`](crate::hash::value::canonical_float) for floating-point values. //! * Use [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices. //! -//! Callers skip empty strings and byte slices before updates. +//! Skip empty strings and byte slices before updating the sketch. mod compression; mod compression_data; diff --git a/datasketches/src/cpc/sketch.rs b/datasketches/src/cpc/sketch.rs index 5ca258b7..9e0eee5a 100644 --- a/datasketches/src/cpc/sketch.rs +++ b/datasketches/src/cpc/sketch.rs @@ -59,8 +59,7 @@ use crate::hash::compute_seed_hash; /// A Compressed Probabilistic Counting sketch. /// -/// For input encodings and empty-input handling, see -/// [Cross-language hashing](crate::cpc#cross-language-hashing). +/// See the [module level documentation](super) for more. #[derive(Clone)] pub struct CpcSketch { // immutable config variables diff --git a/datasketches/src/hash/value/canonical_float.rs b/datasketches/src/hash/value/canonical_float.rs index 7b9acd5f..56a1e082 100644 --- a/datasketches/src/hash/value/canonical_float.rs +++ b/datasketches/src/hash/value/canonical_float.rs @@ -29,8 +29,7 @@ use crate::hash::value::Value; /// A floating-point value wrapper that uses canonical floating-point hashing. /// -/// See the [canonical_float](crate::hash::value::canonical_float) module for encoding details and -/// examples. +/// See the [module level documentation](super) for more. pub type CanonicalFloat = Value; /// Hashing strategy for [`CanonicalFloat`]. diff --git a/datasketches/src/hash/value/natural_extend.rs b/datasketches/src/hash/value/natural_extend.rs index c240d8b2..6d437bde 100644 --- a/datasketches/src/hash/value/natural_extend.rs +++ b/datasketches/src/hash/value/natural_extend.rs @@ -28,8 +28,7 @@ use crate::hash::value::Value; /// An integer value wrapper that uses Rust's natural integer widening before hashing. /// -/// See the [natural_extend](crate::hash::value::natural_extend) module for encoding details and -/// examples. +/// See the [module level documentation](super) for more. pub type NaturalExtend = Value; /// Hashing strategy for [`NaturalExtend`]. diff --git a/datasketches/src/hash/value/raw_bytes.rs b/datasketches/src/hash/value/raw_bytes.rs index 1ec2154f..cc6299a7 100644 --- a/datasketches/src/hash/value/raw_bytes.rs +++ b/datasketches/src/hash/value/raw_bytes.rs @@ -27,7 +27,7 @@ use crate::hash::value::Value; /// A byte or string value wrapper that hashes raw bytes. /// -/// See the [raw_bytes](crate::hash::value::raw_bytes) module for encoding details and examples. +/// See the [module level documentation](super) for more. pub type RawBytes = Value; /// Hashing strategy for [`RawBytes`]. diff --git a/datasketches/src/hash/value/sign_extend.rs b/datasketches/src/hash/value/sign_extend.rs index c8e4c1a9..5486c0a8 100644 --- a/datasketches/src/hash/value/sign_extend.rs +++ b/datasketches/src/hash/value/sign_extend.rs @@ -28,7 +28,7 @@ use crate::hash::value::Value; /// An integer value wrapper that sign-extends the value before hashing. /// -/// See the [sign_extend](crate::hash::value::sign_extend) module for encoding details and examples. +/// See the [module level documentation](super) for more. pub type SignExtend = Value; /// Hashing strategy for [`SignExtend`]. diff --git a/datasketches/src/hll/mod.rs b/datasketches/src/hll/mod.rs index 758f67f0..ed6651c6 100644 --- a/datasketches/src/hll/mod.rs +++ b/datasketches/src/hll/mod.rs @@ -31,7 +31,7 @@ //! * Use [`canonical_float`](crate::hash::value::canonical_float) for floating-point values. //! * Use [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices. //! -//! Callers skip empty strings and byte slices before updates. +//! Skip empty strings and byte slices before updating the sketch. //! //! # Usage //! @@ -122,8 +122,7 @@ const RESIZE_DENOMINATOR: u32 = 4; /// Compute a coupon once with [`Coupon::from_value`] and pass it to /// [`HllSketch::update_with_coupon`] on sketches with any `lg_k` or [`HllType`]. /// -/// For input encodings and empty-input handling, see -/// [Cross-language hashing](crate::hll#cross-language-hashing). +/// See the [module level documentation](crate::hll) for more. /// /// # Examples /// diff --git a/datasketches/src/hll/sketch.rs b/datasketches/src/hll/sketch.rs index a0651a17..a62bea95 100644 --- a/datasketches/src/hll/sketch.rs +++ b/datasketches/src/hll/sketch.rs @@ -55,8 +55,7 @@ use crate::hll::serialization::extract_tgt_hll_type; /// A HyperLogLog sketch. /// -/// For input encodings and empty-input handling, see -/// [Cross-language hashing](crate::hll#cross-language-hashing). +/// See the [module level documentation](super) for more. #[derive(Clone, PartialEq)] pub struct HllSketch { lg_config_k: u8, diff --git a/datasketches/src/thetafamily/theta/mod.rs b/datasketches/src/thetafamily/theta/mod.rs index 0f5dd0d1..2c8bb049 100644 --- a/datasketches/src/thetafamily/theta/mod.rs +++ b/datasketches/src/thetafamily/theta/mod.rs @@ -39,7 +39,7 @@ //! * Use [`canonical_float`](crate::hash::value::canonical_float) for floating-point values. //! * Use [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices. //! -//! Callers skip empty strings and byte slices before updates. +//! Skip empty strings and byte slices before updating the sketch. //! //! # Usage //! diff --git a/datasketches/src/thetafamily/theta/sketch.rs b/datasketches/src/thetafamily/theta/sketch.rs index e9c7579b..e7d0b9b6 100644 --- a/datasketches/src/thetafamily/theta/sketch.rs +++ b/datasketches/src/thetafamily/theta/sketch.rs @@ -204,8 +204,7 @@ impl<'a> From<&'a CompactThetaSketch> for ThetaSketchView<'a> { /// Mutable theta sketch for building from input data. /// -/// For input encodings and empty-input handling, see -/// [Cross-language hashing](crate::theta#cross-language-hashing). +/// See the [module level documentation](super) for more. #[derive(Debug)] pub struct ThetaSketch { table: ThetaHashTable, diff --git a/datasketches/src/thetafamily/tuple/mod.rs b/datasketches/src/thetafamily/tuple/mod.rs index bc12cc39..c6424b0b 100644 --- a/datasketches/src/thetafamily/tuple/mod.rs +++ b/datasketches/src/thetafamily/tuple/mod.rs @@ -37,7 +37,7 @@ //! * Use [`canonical_float`](crate::hash::value::canonical_float) for floating-point values. //! * Use [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices. //! -//! These encodings apply to keys. Callers skip empty string and byte-slice keys before updates. +//! These encodings apply to keys. Skip empty string and byte-slice keys before updating the sketch. //! //! # Usage //! diff --git a/datasketches/src/thetafamily/tuple/sketch.rs b/datasketches/src/thetafamily/tuple/sketch.rs index 901a646a..37bd946d 100644 --- a/datasketches/src/thetafamily/tuple/sketch.rs +++ b/datasketches/src/thetafamily/tuple/sketch.rs @@ -245,8 +245,7 @@ impl<'a, S> From<&'a CompactTupleSketch> for TupleSketchView<'a, S> { /// [`P::Summary`](SummaryPolicy::Summary), while each accepted update type is selected by a /// [`SummaryUpdatePolicy`] implementation. /// -/// For input encodings and empty-input handling, see -/// [Cross-language hashing](crate::tuple#cross-language-hashing). +/// See the [module level documentation](super) for more. /// /// # Examples /// diff --git a/datasketches/src/xor/filter.rs b/datasketches/src/xor/filter.rs index e6acd955..8cd8c1ff 100644 --- a/datasketches/src/xor/filter.rs +++ b/datasketches/src/xor/filter.rs @@ -102,8 +102,7 @@ impl Fingerprints { /// Query values with [`XorFilter::contains`] and precomputed hashes with /// [`XorFilter::contains_hash`]. /// -/// For input encodings and empty-input handling, see -/// [Cross-language hashing](crate::xor#cross-language-hashing). +/// See the [module level documentation](super) for more. #[derive(Debug)] pub struct XorFilterBuilder { filter_type: XorFilterType, @@ -165,8 +164,7 @@ impl XorFilterBuilder { /// empty input set. Values cannot be added after construction; rebuild the filter when the set /// changes. /// -/// For input encodings and empty-input handling, see -/// [Cross-language hashing](crate::xor#cross-language-hashing). +/// See the [module level documentation](super) for more. #[derive(Debug, Clone, PartialEq, Eq)] pub struct XorFilter { // Cache the derived length to avoid division on every query. diff --git a/datasketches/src/xor/mod.rs b/datasketches/src/xor/mod.rs index bc6f6a5d..f31448a3 100644 --- a/datasketches/src/xor/mod.rs +++ b/datasketches/src/xor/mod.rs @@ -29,8 +29,8 @@ //! * Use [`canonical_float`](crate::hash::value::canonical_float) for floating-point values. //! * Use [`raw_bytes`](crate::hash::value::raw_bytes) for UTF-8 strings and byte slices. //! -//! Callers skip empty strings and byte slices when building the filter and return `false` for -//! their membership queries. +//! Skip empty strings and byte slices when building the filter. For these inputs, return +//! `false` without querying the filter. //! //! Value-based APIs use xxHash64 with seed `0`. For precomputed hashes, use the same hash function //! when building and querying the filter, and use the precomputed-hash APIs throughout.