add Deref to Repeatable

honestly, all the unwrapping was just generating noise.
This commit is contained in:
PgBiel 2025-04-20 15:18:31 -03:00
parent 9a01b9bfe8
commit 71ae276071
4 changed files with 32 additions and 27 deletions

View File

@ -238,9 +238,9 @@ impl<'a> GridLayouter<'a> {
while y < self.grid.rows.len() { while y < self.grid.rows.len() {
if let Some(next_header) = self.upcoming_headers.get(consecutive_header_count) if let Some(next_header) = self.upcoming_headers.get(consecutive_header_count)
{ {
if next_header.unwrap().range().contains(&y) { if next_header.range().contains(&y) {
self.place_new_headers(&mut consecutive_header_count, engine)?; self.place_new_headers(&mut consecutive_header_count, engine)?;
y = next_header.unwrap().end; y = next_header.end;
// Skip header rows during normal layout. // Skip header rows during normal layout.
continue; continue;

View File

@ -18,9 +18,8 @@ impl<'a> GridLayouter<'a> {
if new_upcoming_headers.first().is_some_and(|next_header| { if new_upcoming_headers.first().is_some_and(|next_header| {
consecutive_headers.last().is_none_or(|latest_header| { consecutive_headers.last().is_none_or(|latest_header| {
!latest_header.unwrap().short_lived !latest_header.short_lived && next_header.start == latest_header.end
&& next_header.unwrap().start == latest_header.unwrap().end }) && !next_header.short_lived
}) && !next_header.unwrap().short_lived
}) { }) {
// More headers coming, so wait until we reach them. // More headers coming, so wait until we reach them.
// TODO: refactor // TODO: refactor
@ -31,7 +30,7 @@ impl<'a> GridLayouter<'a> {
*consecutive_header_count = 0; *consecutive_header_count = 0;
// Layout short-lived headers immediately. // Layout short-lived headers immediately.
if consecutive_headers.last().is_some_and(|h| h.unwrap().short_lived) { if consecutive_headers.last().is_some_and(|h| h.short_lived) {
// No chance of orphans as we're immediately placing conflicting // No chance of orphans as we're immediately placing conflicting
// headers afterwards, which basically are not headers, for all intents // headers afterwards, which basically are not headers, for all intents
// and purposes. It is therefore guaranteed that all new headers have // and purposes. It is therefore guaranteed that all new headers have
@ -104,7 +103,7 @@ impl<'a> GridLayouter<'a> {
// Assuming non-conflicting headers sorted by increasing y, this must // Assuming non-conflicting headers sorted by increasing y, this must
// be the header with the lowest level (sorted by increasing levels). // be the header with the lowest level (sorted by increasing levels).
let first_level = first_header.unwrap().level; let first_level = first_header.level;
// Stop repeating conflicting headers. // Stop repeating conflicting headers.
// If we go to a new region before the pending headers fit alongside // If we go to a new region before the pending headers fit alongside

View File

@ -1,5 +1,5 @@
use std::num::{NonZeroU32, NonZeroUsize}; use std::num::{NonZeroU32, NonZeroUsize};
use std::ops::Range; use std::ops::{Deref, Range};
use std::sync::Arc; use std::sync::Arc;
use ecow::eco_format; use ecow::eco_format;
@ -487,6 +487,14 @@ pub enum Repeatable<T> {
NotRepeated(T), NotRepeated(T),
} }
impl<T> Deref for Repeatable<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.unwrap()
}
}
impl<T> Repeatable<T> { impl<T> Repeatable<T> {
/// Gets the value inside this repeatable, regardless of whether /// Gets the value inside this repeatable, regardless of whether
/// it repeats. /// it repeats.
@ -1562,10 +1570,10 @@ impl<'x> CellGridResolver<'_, '_, 'x> {
let mut consecutive_header_start = data.start; let mut consecutive_header_start = data.start;
for conflicting_header in for conflicting_header in
headers.iter_mut().rev().take_while(move |h| { headers.iter_mut().rev().take_while(move |h| {
let conflicts = h.unwrap().end == consecutive_header_start let conflicts = h.end == consecutive_header_start
&& h.unwrap().level >= data.level; && h.level >= data.level;
consecutive_header_start = h.unwrap().start; consecutive_header_start = h.start;
conflicts conflicts
}) })
{ {
@ -1818,8 +1826,7 @@ impl<'x> CellGridResolver<'_, '_, 'x> {
// TODO: will need a global slice of headers and footers for // TODO: will need a global slice of headers and footers for
// when we have multiple footers // when we have multiple footers
let last_header_end = let last_header_end = headers.last().map(|header| header.end);
headers.last().map(Repeatable::unwrap).map(|header| header.end);
if has_gutter { if has_gutter {
// Convert the footer's start index to post-gutter coordinates. // Convert the footer's start index to post-gutter coordinates.
@ -1860,11 +1867,11 @@ impl<'x> CellGridResolver<'_, '_, 'x> {
// final footer, as short lived, given that there are no normal rows // final footer, as short lived, given that there are no normal rows
// after them, so repeating them is pointless. // after them, so repeating them is pointless.
let mut consecutive_header_start = let mut consecutive_header_start =
footer.as_ref().map(|f| f.unwrap().start).unwrap_or(row_amount); footer.as_ref().map(|f| f.start).unwrap_or(row_amount);
for header_at_the_end in headers.iter_mut().rev().take_while(move |h| { for header_at_the_end in headers.iter_mut().rev().take_while(move |h| {
let at_the_end = h.unwrap().end == consecutive_header_start; let at_the_end = h.end == consecutive_header_start;
consecutive_header_start = h.unwrap().start; consecutive_header_start = h.start;
at_the_end at_the_end
}) { }) {
header_at_the_end.unwrap_mut().short_lived = true; header_at_the_end.unwrap_mut().short_lived = true;
@ -2052,9 +2059,10 @@ fn check_for_conflicting_cell_row(
// `y + 1 = header.start` holds, that means `y < header.start`, and it // `y + 1 = header.start` holds, that means `y < header.start`, and it
// only occupies one row (`y`), so the cell is actually not in // only occupies one row (`y`), so the cell is actually not in
// conflict. // conflict.
if headers.iter().any(|header| { if headers
cell_y < header.unwrap().end && cell_y + rowspan > header.unwrap().start .iter()
}) { .any(|header| cell_y < header.end && cell_y + rowspan > header.start)
{
bail!( bail!(
"cell would conflict with header spanning the same position"; "cell would conflict with header spanning the same position";
hint: "try moving the cell or the header" hint: "try moving the cell or the header"
@ -2248,11 +2256,9 @@ fn find_next_available_position<const SKIP_ROWS: bool>(
} }
// TODO: consider keeping vector of upcoming headers to make this check // TODO: consider keeping vector of upcoming headers to make this check
// non-quadratic (O(cells) instead of O(headers * cells)). // non-quadratic (O(cells) instead of O(headers * cells)).
} else if let Some(header) = } else if let Some(header) = headers.iter().find(|header| {
headers.iter().map(Repeatable::unwrap).find(|header| { (header.start * columns..header.end * columns).contains(&resolved_index)
(header.start * columns..header.end * columns).contains(&resolved_index) }) {
})
{
// Skip header (can't place a cell inside it from outside it). // Skip header (can't place a cell inside it from outside it).
resolved_index = header.end * columns; resolved_index = header.end * columns;

View File

@ -293,13 +293,13 @@ fn show_cellgrid_html(grid: CellGrid, styles: StyleChain) -> Content {
}; };
let footer = grid.footer.map(|ft| { let footer = grid.footer.map(|ft| {
let rows = rows.drain(ft.unwrap().start..); let rows = rows.drain(ft.start..);
elem(tag::tfoot, Content::sequence(rows.map(|row| tr(tag::td, row)))) elem(tag::tfoot, Content::sequence(rows.map(|row| tr(tag::td, row))))
}); });
// TODO: Headers and footers in arbitrary positions // TODO: Headers and footers in arbitrary positions
// Right now, only those at either end are accepted // Right now, only those at either end are accepted
let header = grid.headers.first().filter(|h| h.unwrap().start == 0).map(|hd| { let header = grid.headers.first().filter(|h| h.start == 0).map(|hd| {
let rows = rows.drain(..hd.unwrap().end); let rows = rows.drain(..hd.end);
elem(tag::thead, Content::sequence(rows.map(|row| tr(tag::th, row)))) elem(tag::thead, Content::sequence(rows.map(|row| tr(tag::th, row))))
}); });