diff --git a/datasketches/src/bloom/mod.rs b/datasketches/src/bloom/mod.rs index 5b2fbce2..e5d67652 100644 --- a/datasketches/src/bloom/mod.rs +++ b/datasketches/src/bloom/mod.rs @@ -33,6 +33,18 @@ //! [`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 +//! +//! For cross-language use, apply the following input conventions: +//! +//! * 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. +//! +//! 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 4dce8ab2..b6dfbe19 100644 --- a/datasketches/src/bloom/sketch.rs +++ b/datasketches/src/bloom/sketch.rs @@ -38,6 +38,8 @@ const EMPTY_FLAG_MASK: u8 = 1 << 2; /// * No false negatives (inserted items always return `true`) /// * Tunable false positive rate /// * Constant space usage +/// +/// 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 03c92838..14855a15 100644 --- a/datasketches/src/countmin/mod.rs +++ b/datasketches/src/countmin/mod.rs @@ -20,30 +20,70 @@ //! 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 use, apply the following input conventions: +//! +//! * 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. +//! +//! 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; -//! 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 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>(()) //! ``` //! -//! # Configuration Helpers +//! ## Empty inputs +//! +//! 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(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 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); +//! 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>(()) //! ``` mod sketch; diff --git a/datasketches/src/countmin/sketch.rs b/datasketches/src/countmin/sketch.rs index f36b2fee..88bf2876 100644 --- a/datasketches/src/countmin/sketch.rs +++ b/datasketches/src/countmin/sketch.rs @@ -45,14 +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 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. +/// See the [module level documentation](super) for more. #[derive(Debug, Clone, PartialEq)] pub struct CountMinSketch { num_hashes: u8, @@ -320,9 +313,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`. @@ -342,9 +332,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 @@ -452,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 /// @@ -507,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 /// @@ -532,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 6102deaf..10c81b39 100644 --- a/datasketches/src/cpc/mod.rs +++ b/datasketches/src/cpc/mod.rs @@ -34,6 +34,17 @@ //! configurations of K. //! //! For additional security this sketch can be configured with a user-specified hash seed. +//! +//! # Cross-language hashing +//! +//! For cross-language use, apply the following input conventions: +//! +//! * 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. +//! +//! 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 d4f688a2..9e0eee5a 100644 --- a/datasketches/src/cpc/sketch.rs +++ b/datasketches/src/cpc/sketch.rs @@ -179,9 +179,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 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..e84df554 100644 --- a/datasketches/src/hash/value/mod.rs +++ b/datasketches/src/hash/value/mod.rs @@ -19,58 +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 a sketch's compatibility rules. +//! 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. //! -//! 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`] -//! * [`canonical_float::from_f64`] -//! -//! ## 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. -//! -//! 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. Use this encoding to match short-integer hashing -//! in DataSketches C++'s Bloom filters and Count-Min sketches. -//! -//! 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 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. -//! -//! 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 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 06db8d35..ed6651c6 100644 --- a/datasketches/src/hll/mod.rs +++ b/datasketches/src/hll/mod.rs @@ -21,8 +21,17 @@ //! [`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 +//! +//! For cross-language use, apply the following input conventions: +//! +//! * 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. +//! +//! Skip empty strings and byte slices before updating the sketch. //! //! # Usage //! @@ -113,6 +122,8 @@ 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`]. /// +/// See the [module level documentation](crate::hll) for more. +/// /// # Examples /// /// ``` @@ -149,9 +160,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..a62bea95 100644 --- a/datasketches/src/hll/sketch.rs +++ b/datasketches/src/hll/sketch.rs @@ -137,9 +137,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 c65fa09e..2c8bb049 100644 --- a/datasketches/src/thetafamily/theta/mod.rs +++ b/datasketches/src/thetafamily/theta/mod.rs @@ -30,6 +30,17 @@ //! * [`ThetaSketch`]: Mutable sketch for building from input data. //! * [`CompactThetaSketch`]: Immutable sketch with a compact memory layout. //! +//! # Cross-language hashing +//! +//! For cross-language use, apply the following input conventions: +//! +//! * 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. +//! +//! 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 4ec71b79..e7d0b9b6 100644 --- a/datasketches/src/thetafamily/theta/sketch.rs +++ b/datasketches/src/thetafamily/theta/sketch.rs @@ -203,6 +203,8 @@ impl<'a> From<&'a CompactThetaSketch> for ThetaSketchView<'a> { } /// Mutable theta sketch for building from input data. +/// +/// See the [module level documentation](super) for more. #[derive(Debug)] pub struct ThetaSketch { table: ThetaHashTable, @@ -218,9 +220,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 c057ee54..c6424b0b 100644 --- a/datasketches/src/thetafamily/tuple/mod.rs +++ b/datasketches/src/thetafamily/tuple/mod.rs @@ -28,6 +28,17 @@ //! summaries of shared keys through [`SummaryCombinePolicy`]; the union defaults to //! [`DefaultUnionPolicy`]. //! +//! # Cross-language hashing +//! +//! For cross-language use, apply the following input conventions: +//! +//! * 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. 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 0fee8218..37bd946d 100644 --- a/datasketches/src/thetafamily/tuple/sketch.rs +++ b/datasketches/src/thetafamily/tuple/sketch.rs @@ -245,6 +245,8 @@ 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. /// +/// See the [module level documentation](super) for more. +/// /// # Examples /// /// ``` diff --git a/datasketches/src/xor/filter.rs b/datasketches/src/xor/filter.rs index b378c8ae..8cd8c1ff 100644 --- a/datasketches/src/xor/filter.rs +++ b/datasketches/src/xor/filter.rs @@ -101,6 +101,8 @@ impl Fingerprints { /// /// Query values with [`XorFilter::contains`] and precomputed hashes with /// [`XorFilter::contains_hash`]. +/// +/// See the [module level documentation](super) for more. #[derive(Debug)] pub struct XorFilterBuilder { filter_type: XorFilterType, @@ -161,6 +163,8 @@ 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. +/// +/// 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 3f146744..f31448a3 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. -//! 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. +//! For cross-language use, apply the following input conventions: +//! +//! * 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. +//! +//! 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. //! //! # Examples //!