Skip to main content

max / makeover-layout

Derive what is left of a windowed set The figure a load-more label prints. In the description layer rather than in each renderer for Showing::selective's reason, and this one has an underflow in it for whoever writes it fourth: a host that overshot its own total would otherwise print a wrapped usize.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-08-16 20:02 UTC
Signed with PGP, not checked
Commit: 7389e98661801ba6f90a24f05ea3e8ce584931df
Parent: e0ae3a7
2 files changed, +34 insertions, -1 deletion
M Cargo.toml +1 -1
@@ -1,6 +1,6 @@
1 1 [package]
2 2 name = "makeover-layout"
3 - version = "0.27.2"
3 + version = "0.27.3"
4 4 edition = "2024"
5 5 # One copy of this vocabulary per dependency graph, enforced by cargo rather
6 6 # than by remembering. Two versions of a description layer in one build means
M src/lib.rs +33
@@ -2422,6 +2422,19 @@
2422 2422 self.from > 0
2423 2423 }
2424 2424
2425 + /// How many sit after this window, when the length is known.
2426 + ///
2427 + /// Here rather than in each renderer for [`Showing::selective`]'s reason:
2428 + /// three of them writing the same subtraction is how they come to disagree,
2429 + /// and this one has an underflow in it for whoever writes it fourth.
2430 + #[must_use]
2431 + pub const fn after(self) -> Option<usize> {
2432 + match self.of {
2433 + Some(of) => Some(of.saturating_sub(self.from.saturating_add(self.count))),
2434 + None => None,
2435 + }
2436 + }
2437 +
2425 2438 /// Whether anything sits after it.
2426 2439 ///
2427 2440 /// `true` when the length is unknown: a host that cannot count cannot rule
@@ -2554,6 +2567,16 @@
2554 2567 self.window.of
2555 2568 }
2556 2569
2570 + /// How many are not shown yet, when the host counted.
2571 + ///
2572 + /// The figure a load-more control puts in its label. `None` is the honest
2573 + /// and common case: a set that cannot say how many more there are still has
2574 + /// a way to ask for them.
2575 + #[must_use]
2576 + pub const fn remaining(self) -> Option<usize> {
2577 + self.window.after()
2578 + }
2579 +
2557 2580 /// Whether there is anything further on.
2558 2581 #[must_use]
2559 2582 pub const fn has_more(self) -> bool {
@@ -4637,6 +4660,16 @@
4637 4660 let feed = Paging::more(50);
4638 4661 assert_eq!(feed.total(), None);
4639 4662 assert_eq!(feed.pages_total(), None);
4663 + assert_eq!(feed.remaining(), None);
4640 4664 assert!(feed.has_more());
4641 4665 }
4666 +
4667 + #[test]
4668 + fn what_is_left_is_derived_and_never_underflows() {
4669 + assert_eq!(Paging::more(150).of(400).remaining(), Some(250));
4670 + assert_eq!(Paging::pages(350, 50).of(400).remaining(), Some(0));
4671 + // A host that overshot its own total gets zero rather than a wrapped
4672 + // usize, which would print as "18446744073709551516 remaining".
4673 + assert_eq!(Paging::more(500).of(400).remaining(), Some(0));
4674 + }
4642 4675 }