size_hinter

Crates.iosize_hinter
lib.rssize_hinter
version0.4.0
created_at2025-12-23 12:02:43.338603+00
updated_at2026-01-24 12:02:25.328432+00
descriptionIterator adaptors allowing overriding or specifying size_hint.
homepagehttps://github.com/MaxMahem/size_hinter
repositoryhttps://github.com/MaxMahem/size_hinter
max_upload_size
id2001394
size94,784
Austin Stanley (MaxMahem)

documentation

https://docs.rs/size_hinter

README

size_hinter

Build Docs dependency status Crates.io codecov GitHub License

Iterator adaptors for overriding or specifying exact size hints in Rust.

Overview

size_hinter provides two iterator adaptors, an extension trait, and a foundational type for working with iterator size hints.

  • SizeHint: An immutable type representing a size hint with strong guarantees about bounds validity (lower <= upper), providing additional functionality and conversions.
  • ExactLen: Wraps an iterator to provide an exact length via ExactSizeIterator::len() and a coresponding Iterator::size_hint(). This is useful when you know the exact length of an iterator that doesn't normally implement ExactSizeIterator (like Filter).
  • HintSize: Wraps an Iterator in an adaptor that provides a custom Iterator::size_hint() implementation only. This is primarily useful for implementing a fixed universal size hint (0, None) for testing.
  • InvalidIterator: An iterator that reports an invalid size hint (lower > upper).
  • SizeHinter: An extension trait for fluently creating these adaptors.

This crate is no_std compatible and contains no unsafe code.

Installation

It's on crates.io.

Usage

ExactLen - Adding Exact Length to Iterators

ExactLen provides an exact length via ExactSizeIterator::len() and a coresponding Iterator::size_hint(). This is useful when you know the exact length of an iterator that doesn't normally implement ExactSizeIterator (like Filter), and may allow for some performance optimizations.

use size_hinter::SizeHinter;

// Filter doesn't implement ExactSizeIterator, but we know there are 3 odd numbers
let mut nums = (1..=5).filter(|x| x % 2 == 1).exact_len(3);

assert_eq!(nums.len(), 3, "Length should be 3");
assert_eq!(nums.size_hint(), (3, Some(3)), "Size hint should match length");

assert_eq!(nums.next(), Some(1), "Underlying iterator should be unchanged");
assert_eq!(nums.len(), 2, "Length should change to match remaining elements");
assert_eq!(nums.size_hint(), (2, Some(2)), "Size hint should match length");

assert_eq!(nums.next_back(), Some(5), "DoubleEndedIterator::next_back should work as expected");
assert_eq!(nums.len(), 1, "Length should change to match remaining elements");
assert_eq!(nums.size_hint(), (1, Some(1)), "Size hint should match length");

HintSize - Overrides Size Hints

HintSize provides a custom Iterator::size_hint() implementation. This is primarily useful for implementing a fixed universal size hint (0, None) for testing, but any valid size hint can be provided.

use size_hinter::SizeHinter;

// Hide the size hint completely (returns (0, None))
let mut hidden = vec![1, 2, 3].into_iter().hide_size();
assert_eq!(hidden.size_hint(), (0, None), "Size hint is hidden");
assert_eq!(hidden.next(), Some(1), "Underlying iterator is not changed");
assert_eq!(hidden.size_hint(), (0, None), "Size hint remains hidden");

// Provide a custom size hint
let mut custom = vec![1, 2, 3].into_iter().hint_size(1, 10);
assert_eq!(custom.size_hint(), (1, Some(10)), "Size hint is set to (1, Some(10))");
assert_eq!(custom.next(), Some(1), "Underlying iterator is not changed");
assert_eq!(custom.size_hint(), (0, Some(9)), "Size hint is updated to (0, Some(9))");

SizeHint - Working with Size Hints Directly

SizeHint is a type-safe wrapper around the standard iterator size hint tuple (usize, Option<usize>). It provides strong guarantees about bound validity and offers additional functionality for working with size hints.

use size_hinter::SizeHint;

// Create a bounded size hint (min 2, max 10 elements)
let hint = SizeHint::bounded(2, 10);
assert_eq!(hint.lower, 2);
assert_eq!(hint.upper, Some(10));

// Create an exact size hint
let exact = SizeHint::exact(5);
assert_eq!(exact.lower, 5);
assert_eq!(exact.upper, Some(5));

// Create an unbounded size hint (at least 3 elements, no upper limit)
let unbounded = SizeHint::unbounded(3);
assert_eq!(unbounded.lower, 3);
assert_eq!(unbounded.upper, None);

// Check if two size hints overlap
assert!(SizeHint::bounded(3, 6).overlaps(SizeHint::bounded(5, 10)));
assert!(SizeHint::exact(5).disjoint(SizeHint::bounded(10, 20)));

Adaptor Performance Considerations

Wrapping an iterator that does not provide a detailed size hint or implement ExactSizeIterator may allow for some optimizations or performance improvements. However, it may lead to performance penalties if the wrapped iterator already implements TrustedLen, even if it does not implement ExactSizeIterator. For example, std::iter::Chain. Since this adaptor hides that implementation.

Safety

ExactLen and HintSize are always safe to use - they will never cause undefined behavior or memory unsafety, regardless of the values provided.

Both adaptors validate that provided hints/lengths are logical (lower bound <= upper bound) and don't contradict the wrapped iterator's stated bounds. An adaptor can provide a hint or length that introduces new information, such as a new lower bound that is higher than provided one, but cannot claim a new lower bound higher than the wrapped iterator's max bound (if present).

It is still the caller's responsibility to ensure that the provided hints/lengths are accurate. Inaccurate values may prevent optimizations or cause issues in code that relies on these values for allocation or other decisions.

Commit count: 40

cargo fmt