diff --git a/crates/typst-layout/src/grid/layouter.rs b/crates/typst-layout/src/grid/layouter.rs index 697bef225..7b10f06d9 100644 --- a/crates/typst-layout/src/grid/layouter.rs +++ b/crates/typst-layout/src/grid/layouter.rs @@ -238,9 +238,9 @@ impl<'a> GridLayouter<'a> { while y < self.grid.rows.len() { 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)?; - y = next_header.unwrap().end; + y = next_header.end; // Skip header rows during normal layout. continue; diff --git a/crates/typst-layout/src/grid/repeated.rs b/crates/typst-layout/src/grid/repeated.rs index 01a087330..9a4ebbefe 100644 --- a/crates/typst-layout/src/grid/repeated.rs +++ b/crates/typst-layout/src/grid/repeated.rs @@ -18,9 +18,8 @@ impl<'a> GridLayouter<'a> { if new_upcoming_headers.first().is_some_and(|next_header| { consecutive_headers.last().is_none_or(|latest_header| { - !latest_header.unwrap().short_lived - && next_header.unwrap().start == latest_header.unwrap().end - }) && !next_header.unwrap().short_lived + !latest_header.short_lived && next_header.start == latest_header.end + }) && !next_header.short_lived }) { // More headers coming, so wait until we reach them. // TODO: refactor @@ -31,7 +30,7 @@ impl<'a> GridLayouter<'a> { *consecutive_header_count = 0; // 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 // headers afterwards, which basically are not headers, for all intents // 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 // 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. // If we go to a new region before the pending headers fit alongside diff --git a/crates/typst-library/src/layout/grid/resolve.rs b/crates/typst-library/src/layout/grid/resolve.rs index 9c872155a..4ecdb44b2 100644 --- a/crates/typst-library/src/layout/grid/resolve.rs +++ b/crates/typst-library/src/layout/grid/resolve.rs @@ -1,5 +1,5 @@ use std::num::{NonZeroU32, NonZeroUsize}; -use std::ops::Range; +use std::ops::{Deref, Range}; use std::sync::Arc; use ecow::eco_format; @@ -487,6 +487,14 @@ pub enum Repeatable { NotRepeated(T), } +impl Deref for Repeatable { + type Target = T; + + fn deref(&self) -> &Self::Target { + self.unwrap() + } +} + impl Repeatable { /// Gets the value inside this repeatable, regardless of whether /// it repeats. @@ -1562,10 +1570,10 @@ impl<'x> CellGridResolver<'_, '_, 'x> { let mut consecutive_header_start = data.start; for conflicting_header in headers.iter_mut().rev().take_while(move |h| { - let conflicts = h.unwrap().end == consecutive_header_start - && h.unwrap().level >= data.level; + let conflicts = h.end == consecutive_header_start + && h.level >= data.level; - consecutive_header_start = h.unwrap().start; + consecutive_header_start = h.start; conflicts }) { @@ -1818,8 +1826,7 @@ impl<'x> CellGridResolver<'_, '_, 'x> { // TODO: will need a global slice of headers and footers for // when we have multiple footers - let last_header_end = - headers.last().map(Repeatable::unwrap).map(|header| header.end); + let last_header_end = headers.last().map(|header| header.end); if has_gutter { // 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 // after them, so repeating them is pointless. 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| { - 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 }) { 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 // only occupies one row (`y`), so the cell is actually not in // conflict. - if headers.iter().any(|header| { - cell_y < header.unwrap().end && cell_y + rowspan > header.unwrap().start - }) { + if headers + .iter() + .any(|header| cell_y < header.end && cell_y + rowspan > header.start) + { bail!( "cell would conflict with header spanning the same position"; hint: "try moving the cell or the header" @@ -2248,11 +2256,9 @@ fn find_next_available_position( } // TODO: consider keeping vector of upcoming headers to make this check // non-quadratic (O(cells) instead of O(headers * cells)). - } else if let Some(header) = - headers.iter().map(Repeatable::unwrap).find(|header| { - (header.start * columns..header.end * columns).contains(&resolved_index) - }) - { + } else if let Some(header) = headers.iter().find(|header| { + (header.start * columns..header.end * columns).contains(&resolved_index) + }) { // Skip header (can't place a cell inside it from outside it). resolved_index = header.end * columns; diff --git a/crates/typst-library/src/model/table.rs b/crates/typst-library/src/model/table.rs index 86ef59ed1..5a0b1f857 100644 --- a/crates/typst-library/src/model/table.rs +++ b/crates/typst-library/src/model/table.rs @@ -293,13 +293,13 @@ fn show_cellgrid_html(grid: CellGrid, styles: StyleChain) -> Content { }; 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)))) }); // TODO: Headers and footers in arbitrary positions // Right now, only those at either end are accepted - let header = grid.headers.first().filter(|h| h.unwrap().start == 0).map(|hd| { - let rows = rows.drain(..hd.unwrap().end); + let header = grid.headers.first().filter(|h| h.start == 0).map(|hd| { + let rows = rows.drain(..hd.end); elem(tag::thead, Content::sequence(rows.map(|row| tr(tag::th, row)))) });