From 97379e4434b34128f29e1eeb9d4e96ce00b427c3 Mon Sep 17 00:00:00 2001 From: cgzones Date: Mon, 17 Nov 2025 18:33:17 +0100 Subject: [PATCH 1/2] feat(SizeHint): derive `Copy` trait The struct has only a size of 24 bytes and is trivially copy-able. --- http-body/src/size_hint.rs | 8 ++++---- http-body/tests/is_end_stream.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/http-body/src/size_hint.rs b/http-body/src/size_hint.rs index 4b477fc..1492d63 100644 --- a/http-body/src/size_hint.rs +++ b/http-body/src/size_hint.rs @@ -4,7 +4,7 @@ /// /// * 0 for `lower` /// * `None` for `upper`. -#[derive(Debug, Default, Clone)] +#[derive(Debug, Default, Clone, Copy)] pub struct SizeHint { lower: u64, upper: Option, @@ -178,7 +178,7 @@ fn size_hint_addition_basic() { let exact_l = SizeHint::with_exact(20); let exact_r = SizeHint::with_exact(5); - assert_eq!(Some(25), (exact_l.clone() + exact_r).exact()); + assert_eq!(Some(25), (exact_l + exact_r).exact()); let inexact_l = SizeHint { lower: 25, @@ -189,12 +189,12 @@ fn size_hint_addition_basic() { upper: Some(50), }; - let inexact = inexact_l + inexact_r.clone(); + let inexact = inexact_l + inexact_r; assert_eq!(inexact.lower(), 35); assert_eq!(inexact.upper(), None); - let exact_inexact = exact_l.clone() + inexact_r.clone(); + let exact_inexact = exact_l + inexact_r; assert_eq!(exact_inexact.lower(), 30); assert_eq!(exact_inexact.upper(), Some(70)); diff --git a/http-body/tests/is_end_stream.rs b/http-body/tests/is_end_stream.rs index 94b7c3d..9ea69a8 100644 --- a/http-body/tests/is_end_stream.rs +++ b/http-body/tests/is_end_stream.rs @@ -18,7 +18,7 @@ impl Body for Mock { } fn size_hint(&self) -> SizeHint { - self.size_hint.clone() + self.size_hint } } From 187628c09653931ce9a60bd0e9788f0f850ee2a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Sat, 22 Nov 2025 15:46:40 +0100 Subject: [PATCH 2/2] feat(SizeHint): add `must_use` annotations and permit `const` contexts Permit `SizeHint` operations in const contexts and warn on unused results from constructors or getters without side-effects. --- http-body/src/size_hint.rs | 52 ++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/http-body/src/size_hint.rs b/http-body/src/size_hint.rs index 1492d63..3398ba7 100644 --- a/http-body/src/size_hint.rs +++ b/http-body/src/size_hint.rs @@ -13,14 +13,19 @@ pub struct SizeHint { impl SizeHint { /// Returns a new `SizeHint` with default values #[inline] - pub fn new() -> SizeHint { - SizeHint::default() + #[must_use] + pub const fn new() -> SizeHint { + Self { + lower: 0, + upper: None, + } } /// Returns a new `SizeHint` with both upper and lower bounds set to the /// given value. #[inline] - pub fn with_exact(value: u64) -> SizeHint { + #[must_use] + pub const fn with_exact(value: u64) -> SizeHint { SizeHint { lower: value, upper: Some(value), @@ -30,7 +35,8 @@ impl SizeHint { /// Returns the lower bound of data that the `Body` will yield before /// completing. #[inline] - pub fn lower(&self) -> u64 { + #[must_use] + pub const fn lower(&self) -> u64 { self.lower } @@ -40,15 +46,19 @@ impl SizeHint { /// /// The function panics if `value` is greater than `upper`. #[inline] - pub fn set_lower(&mut self, value: u64) { - assert!(value <= self.upper.unwrap_or(u64::MAX)); + pub const fn set_lower(&mut self, value: u64) { + assert!(match self.upper { + Some(upper) => value <= upper, + None => true, + }); self.lower = value; } /// Returns the upper bound of data the `Body` will yield before /// completing, or `None` if the value is unknown. #[inline] - pub fn upper(&self) -> Option { + #[must_use] + pub const fn upper(&self) -> Option { self.upper } @@ -58,7 +68,7 @@ impl SizeHint { /// /// This function panics if `value` is less than `lower`. #[inline] - pub fn set_upper(&mut self, value: u64) { + pub const fn set_upper(&mut self, value: u64) { assert!(value >= self.lower, "`value` is less than than `lower`"); self.upper = Some(value); @@ -67,17 +77,18 @@ impl SizeHint { /// Returns the exact size of data that will be yielded **if** the /// `lower` and `upper` bounds are equal. #[inline] - pub fn exact(&self) -> Option { - if Some(self.lower) == self.upper { - self.upper - } else { - None + #[must_use] + pub const fn exact(&self) -> Option { + match self.upper { + Some(upper) if self.lower == upper => Some(upper), + Some(_) | None => None, } } /// Set the value of the `lower` and `upper` bounds to exactly the same. #[inline] - pub fn set_exact(&mut self, value: u64) { + #[must_use] + pub const fn set_exact(&mut self, value: u64) { self.lower = value; self.upper = Some(value); } @@ -97,6 +108,19 @@ impl core::ops::Add for SizeHint { } } +#[test] +fn size_init_new_default() { + let new = SizeHint::new(); + assert_eq!(new.lower(), 0); + assert_eq!(new.upper(), None); + assert_eq!(new.exact(), None); + + let def = SizeHint::default(); + assert_eq!(def.lower(), 0); + assert_eq!(def.upper(), None); + assert_eq!(def.exact(), None); +} + /// Asserts that SizeHint addition is perfect with a basic proof #[test] fn size_hint_addition_proof() {