refactor: Avoid unneeded allocations (#1345)

This commit is contained in:
Mo 2024-08-26 22:59:30 +02:00 committed by GitHub
parent e02947be61
commit 20c88aaa5b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 62 additions and 108 deletions

View file

@ -14,7 +14,6 @@
//! [examples readme]: https://github.com/ratatui/ratatui/blob/main/examples/README.md
use color_eyre::Result;
use itertools::Itertools;
use ratatui::{
crossterm::event::{self, Event, KeyCode, KeyEventKind},
layout::{Alignment, Constraint, Layout, Rect},
@ -90,7 +89,7 @@ fn calculate_layout(area: Rect) -> (Rect, Vec<Vec<Rect>>) {
.split(area)
.to_vec()
})
.collect_vec();
.collect();
(title_area, main_areas)
}

View file

@ -99,19 +99,16 @@ fn render_fg_named_colors(frame: &mut Frame, bg: Color, area: Rect) {
let inner = block.inner(area);
frame.render_widget(block, area);
let layout = Layout::vertical([Constraint::Length(1); 2])
.split(inner)
.iter()
.flat_map(|area| {
Layout::horizontal([Constraint::Ratio(1, 8); 8])
.split(*area)
.to_vec()
})
.collect_vec();
for (i, &fg) in NAMED_COLORS.iter().enumerate() {
let vertical = Layout::vertical([Constraint::Length(1); 2]).split(inner);
let areas = vertical.iter().flat_map(|area| {
Layout::horizontal([Constraint::Ratio(1, 8); 8])
.split(*area)
.to_vec()
});
for (fg, area) in NAMED_COLORS.into_iter().zip(areas) {
let color_name = fg.to_string();
let paragraph = Paragraph::new(color_name).fg(fg).bg(bg);
frame.render_widget(paragraph, layout[i]);
frame.render_widget(paragraph, area);
}
}
@ -120,19 +117,16 @@ fn render_bg_named_colors(frame: &mut Frame, fg: Color, area: Rect) {
let inner = block.inner(area);
frame.render_widget(block, area);
let layout = Layout::vertical([Constraint::Length(1); 2])
.split(inner)
.iter()
.flat_map(|area| {
Layout::horizontal([Constraint::Ratio(1, 8); 8])
.split(*area)
.to_vec()
})
.collect_vec();
for (i, &bg) in NAMED_COLORS.iter().enumerate() {
let vertical = Layout::vertical([Constraint::Length(1); 2]).split(inner);
let areas = vertical.iter().flat_map(|area| {
Layout::horizontal([Constraint::Ratio(1, 8); 8])
.split(*area)
.to_vec()
});
for (bg, area) in NAMED_COLORS.into_iter().zip(areas) {
let color_name = bg.to_string();
let paragraph = Paragraph::new(color_name).fg(fg).bg(bg);
frame.render_widget(paragraph, layout[i]);
frame.render_widget(paragraph, area);
}
}

View file

@ -346,13 +346,8 @@ impl App {
}
fn render_user_constraints_legend(&self, area: Rect, buf: &mut Buffer) {
let blocks = Layout::horizontal(
self.constraints
.iter()
.map(|_| Constraint::Fill(1))
.collect_vec(),
)
.split(area);
let constraints = self.constraints.iter().map(|_| Constraint::Fill(1));
let blocks = Layout::horizontal(constraints).split(area);
for (i, (area, constraint)) in blocks.iter().zip(self.constraints.iter()).enumerate() {
let selected = self.selected_index == i;

View file

@ -96,13 +96,10 @@ fn render_inbox(selected_index: usize, area: Rect, buf: &mut Buffer) {
.map(|e| e.from.width())
.max()
.unwrap_or_default();
let items = EMAILS
.iter()
.map(|e| {
let from = format!("{:width$}", e.from, width = from_width).into();
ListItem::new(Line::from(vec![from, " ".into(), e.subject.into()]))
})
.collect_vec();
let items = EMAILS.iter().map(|e| {
let from = format!("{:width$}", e.from, width = from_width).into();
ListItem::new(Line::from(vec![from, " ".into(), e.subject.into()]))
});
let mut state = ListState::default().with_selected(Some(selected_index));
StatefulWidget::render(
List::new(items)

View file

@ -52,10 +52,7 @@ impl Widget for TracerouteTab {
fn render_hops(selected_row: usize, area: Rect, buf: &mut Buffer) {
let mut state = TableState::default().with_selected(Some(selected_row));
let rows = HOPS
.iter()
.map(|hop| Row::new(vec![hop.host, hop.address]))
.collect_vec();
let rows = HOPS.iter().map(|hop| Row::new(vec![hop.host, hop.address]));
let block = Block::new()
.padding(Padding::new(1, 1, 1, 1))
.title_alignment(Alignment::Center)

View file

@ -74,31 +74,28 @@ fn draw(frame: &mut Frame) {
Min(0), // fills remaining space
])
.split(examples_area);
let example_areas = example_rows
let example_areas = example_rows.iter().flat_map(|area| {
Layout::horizontal([
Length(14),
Length(14),
Length(14),
Length(14),
Length(14),
Min(0), // fills remaining space
])
.split(*area)
.iter()
.flat_map(|area| {
Layout::horizontal([
Length(14),
Length(14),
Length(14),
Length(14),
Length(14),
Min(0), // fills remaining space
])
.split(*area)
.iter()
.copied()
.take(5) // ignore Min(0)
.collect_vec()
})
.collect_vec();
.copied()
.take(5) // ignore Min(0)
.collect_vec()
});
// the examples are a cartesian product of the following constraints
// e.g. Len/Len, Len/Min, Len/Max, Len/Perc, Len/Ratio, Min/Len, Min/Min, ...
let examples = [
(
"Len",
vec![
[
Length(0),
Length(2),
Length(3),
@ -107,17 +104,11 @@ fn draw(frame: &mut Frame) {
Length(15),
],
),
(
"Min",
vec![Min(0), Min(2), Min(3), Min(6), Min(10), Min(15)],
),
(
"Max",
vec![Max(0), Max(2), Max(3), Max(6), Max(10), Max(15)],
),
("Min", [Min(0), Min(2), Min(3), Min(6), Min(10), Min(15)]),
("Max", [Max(0), Max(2), Max(3), Max(6), Max(10), Max(15)]),
(
"Perc",
vec![
[
Percentage(0),
Percentage(25),
Percentage(50),
@ -128,7 +119,7 @@ fn draw(frame: &mut Frame) {
),
(
"Ratio",
vec![
[
Ratio(0, 4),
Ratio(1, 4),
Ratio(2, 4),
@ -139,24 +130,15 @@ fn draw(frame: &mut Frame) {
),
];
for (i, (a, b)) in examples
for ((a, b), area) in examples
.iter()
.cartesian_product(examples.iter())
.enumerate()
.zip(example_areas)
{
let (name_a, examples_a) = a;
let (name_b, examples_b) = b;
let constraints = examples_a
.iter()
.copied()
.zip(examples_b.iter().copied())
.collect_vec();
render_example_combination(
frame,
example_areas[i],
&format!("{name_a}/{name_b}"),
constraints,
);
let constraints = examples_a.iter().copied().zip(examples_b.iter().copied());
render_example_combination(frame, area, &format!("{name_a}/{name_b}"), constraints);
}
}
@ -165,7 +147,7 @@ fn render_example_combination(
frame: &mut Frame,
area: Rect,
title: &str,
constraints: Vec<(Constraint, Constraint)>,
constraints: impl ExactSizeIterator<Item = (Constraint, Constraint)>,
) {
let block = Block::bordered()
.title(title.gray())
@ -174,8 +156,8 @@ fn render_example_combination(
let inner = block.inner(area);
frame.render_widget(block, area);
let layout = Layout::vertical(vec![Length(1); constraints.len() + 1]).split(inner);
for (i, (a, b)) in constraints.into_iter().enumerate() {
render_single_example(frame, layout[i], vec![a, b, Min(0)]);
for ((a, b), &area) in constraints.into_iter().zip(layout.iter()) {
render_single_example(frame, area, vec![a, b, Min(0)]);
}
// This is to make it easy to visually see the alignment of the examples
// with the constraints.

View file

@ -294,7 +294,7 @@ fn generate_fake_names() -> Vec<Data> {
}
})
.sorted_by(|a, b| a.name.cmp(&b.name))
.collect_vec()
.collect()
}
fn constraint_len_calculator(items: &[Data]) -> (u16, u16, u16) {

View file

@ -1,6 +1,5 @@
use std::fmt;
use itertools::Itertools;
use strum::EnumIs;
/// A constraint that defines the size of a layout element.
@ -229,7 +228,7 @@ impl Constraint {
where
T: IntoIterator<Item = u16>,
{
lengths.into_iter().map(Self::Length).collect_vec()
lengths.into_iter().map(Self::Length).collect()
}
/// Convert an iterator of ratios into a vector of constraints
@ -246,10 +245,7 @@ impl Constraint {
where
T: IntoIterator<Item = (u32, u32)>,
{
ratios
.into_iter()
.map(|(n, d)| Self::Ratio(n, d))
.collect_vec()
ratios.into_iter().map(|(n, d)| Self::Ratio(n, d)).collect()
}
/// Convert an iterator of percentages into a vector of constraints
@ -266,7 +262,7 @@ impl Constraint {
where
T: IntoIterator<Item = u16>,
{
percentages.into_iter().map(Self::Percentage).collect_vec()
percentages.into_iter().map(Self::Percentage).collect()
}
/// Convert an iterator of maxes into a vector of constraints
@ -283,7 +279,7 @@ impl Constraint {
where
T: IntoIterator<Item = u16>,
{
maxes.into_iter().map(Self::Max).collect_vec()
maxes.into_iter().map(Self::Max).collect()
}
/// Convert an iterator of mins into a vector of constraints
@ -300,7 +296,7 @@ impl Constraint {
where
T: IntoIterator<Item = u16>,
{
mins.into_iter().map(Self::Min).collect_vec()
mins.into_iter().map(Self::Min).collect()
}
/// Convert an iterator of proportional factors into a vector of constraints
@ -317,10 +313,7 @@ impl Constraint {
where
T: IntoIterator<Item = u16>,
{
proportional_factors
.into_iter()
.map(Self::Fill)
.collect_vec()
proportional_factors.into_iter().map(Self::Fill).collect()
}
}

View file

@ -1315,9 +1315,9 @@ mod tests {
.flex(flex)
.split(area);
let mut buffer = Buffer::empty(area);
for (i, c) in ('a'..='z').take(constraints.len()).enumerate() {
for (c, &area) in ('a'..='z').take(constraints.len()).zip(layout.iter()) {
let s = c.to_string().repeat(area.width as usize);
Paragraph::new(s).render(layout[i], &mut buffer);
Paragraph::new(s).render(area, &mut buffer);
}
assert_eq!(buffer, Buffer::with_lines([expected]));
}

View file

@ -1,8 +1,6 @@
#![warn(missing_docs)]
use std::{borrow::Cow, fmt};
use itertools::{Itertools, Position};
use crate::{prelude::*, style::Styled};
/// A string split over one or more lines.
@ -632,12 +630,11 @@ impl<T: fmt::Display> ToText for T {
impl fmt::Display for Text<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for (position, line) in self.iter().with_position() {
if position == Position::Last || position == Position::Only {
write!(f, "{line}")?;
} else {
if let Some((last, rest)) = self.lines.split_last() {
for line in rest {
writeln!(f, "{line}")?;
}
write!(f, "{last}")?;
}
Ok(())
}