From 8f155dc6a21a3f5bd8582ad0f8985541680b5369 Mon Sep 17 00:00:00 2001 From: Joscha Date: Sun, 19 Feb 2023 02:09:41 +0100 Subject: [PATCH] Fix join widgets not handling large sizes --- src/widgets/join.rs | 74 +++++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/src/widgets/join.rs b/src/widgets/join.rs index ef6e989..2a0a7b5 100644 --- a/src/widgets/join.rs +++ b/src/widgets/join.rs @@ -51,8 +51,7 @@ use super::{Either2, Either3, Either4, Either5, Either6, Either7}; // removes all segments that are at least as small as their allotment. It then // resizes the remaining segments to their allotments. -// TODO Handle overflows and other sizing issues correctly - +#[derive(Debug)] struct Segment { size: u16, weight: f32, @@ -74,13 +73,24 @@ impl Segment { } } +fn total_size(segments: &[Segment]) -> u16 { + let mut total = 0_u16; + for segment in segments { + total = total.saturating_add(segment.size); + } + total +} + +fn total_weight(segments: &[&mut Segment]) -> f32 { + segments.iter().map(|s| s.weight).sum() +} + fn balance(segments: &mut [Segment], available: u16) { if segments.is_empty() { return; } - let total_size = segments.iter().map(|s| s.size).sum::(); - match total_size.cmp(&available) { + match total_size(segments).cmp(&available) { Ordering::Less => grow(segments, available), Ordering::Greater => shrink(segments, available), Ordering::Equal => {} @@ -90,13 +100,13 @@ fn balance(segments: &mut [Segment], available: u16) { } fn grow(segments: &mut [Segment], mut available: u16) { - assert!(available > segments.iter().map(|s| s.size).sum::()); + assert!(available > total_size(segments)); let mut segments = segments.iter_mut().collect::>(); // Repeatedly remove all segments that do not need to grow, i. e. that are // at least as large as their allotment. loop { - let mut total_weight = segments.iter().map(|s| s.weight).sum::(); + let mut total_weight = total_weight(&segments); // If there are no segments with a weight > 0, space is distributed // evenly among all remaining segments. @@ -149,13 +159,13 @@ fn grow(segments: &mut [Segment], mut available: u16) { } fn shrink(segments: &mut [Segment], mut available: u16) { - assert!(available < segments.iter().map(|s| s.size).sum::()); + assert!(available < total_size(segments)); let mut segments = segments.iter_mut().collect::>(); // Repeatedly remove all segments that do not need to shrink, i. e. that are // at least as small as their allotment. loop { - let mut total_weight = segments.iter().map(|s| s.weight).sum::(); + let mut total_weight = total_weight(&segments); // If there are no segments with a weight > 0, space is distributed // evenly among all remaining segments. @@ -258,20 +268,20 @@ where } balance(&mut balanced_segments, max_width); - let mut width = 0; - let mut height = 0; + let mut width = 0_u16; + let mut height = 0_u16; for (segment, balanced) in self.segments.iter().zip(balanced_segments.into_iter()) { let size = segment.inner.size(frame, Some(balanced.size), max_height)?; - width += size.width; + width = width.saturating_add(size.width); height = height.max(size.height); } Ok(Size::new(width, height)) } else { - let mut width = 0; - let mut height = 0; + let mut width = 0_u16; + let mut height = 0_u16; for segment in &self.segments { let size = segment.inner.size(frame, max_width, max_height)?; - width += size.width; + width = width.saturating_add(size.width); height = height.max(size.height); } Ok(Size::new(width, height)) @@ -324,23 +334,23 @@ where } balance(&mut balanced_segments, max_width); - let mut width = 0; - let mut height = 0; + let mut width = 0_u16; + let mut height = 0_u16; for (segment, balanced) in self.segments.iter().zip(balanced_segments.into_iter()) { let size = segment .inner .size(frame, Some(balanced.size), max_height) .await?; - width += size.width; + width = width.saturating_add(size.width); height = height.max(size.height); } Ok(Size::new(width, height)) } else { - let mut width = 0; - let mut height = 0; + let mut width = 0_u16; + let mut height = 0_u16; for segment in &self.segments { let size = segment.inner.size(frame, max_width, max_height).await?; - width += size.width; + width = width.saturating_add(size.width); height = height.max(size.height); } Ok(Size::new(width, height)) @@ -399,21 +409,21 @@ where } balance(&mut balanced_segments, max_height); - let mut width = 0; - let mut height = 0; + let mut width = 0_u16; + let mut height = 0_u16; for (segment, balanced) in self.segments.iter().zip(balanced_segments.into_iter()) { let size = segment.inner.size(frame, max_width, Some(balanced.size))?; width = width.max(size.width); - height += size.height; + height = height.saturating_add(size.height); } Ok(Size::new(width, height)) } else { - let mut width = 0; - let mut height = 0; + let mut width = 0_u16; + let mut height = 0_u16; for segment in &self.segments { let size = segment.inner.size(frame, max_width, max_height)?; width = width.max(size.width); - height += size.height; + height = height.saturating_add(size.height); } Ok(Size::new(width, height)) } @@ -465,24 +475,24 @@ where } balance(&mut balanced_segments, max_height); - let mut width = 0; - let mut height = 0; + let mut width = 0_u16; + let mut height = 0_u16; for (segment, balanced) in self.segments.iter().zip(balanced_segments.into_iter()) { let size = segment .inner .size(frame, max_width, Some(balanced.size)) .await?; width = width.max(size.width); - height += size.height; + height = height.saturating_add(size.height); } Ok(Size::new(width, height)) } else { - let mut width = 0; - let mut height = 0; + let mut width = 0_u16; + let mut height = 0_u16; for segment in &self.segments { let size = segment.inner.size(frame, max_width, max_height).await?; width = width.max(size.width); - height += size.height; + height = height.saturating_add(size.height); } Ok(Size::new(width, height)) }