mirror of
https://github.com/storytold/wordcraft.git
synced 2026-11-06 10:19:59 -06:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e49aaf0072 |
+2
-2
File diff suppressed because one or more lines are too long
@@ -58,6 +58,23 @@ mod tests {
|
||||
assert!(t.rows.iter().all(|r| r.len() <= 64), "a row grew past the column cap");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_covered_skips_full_rows_without_walking_them() {
|
||||
// 50,000 spanning cells over a 50,000-cell row: each walked the row below to its grid
|
||||
// column before finding it full (billions of steps). A full row is now skipped at once.
|
||||
let n = 50_000;
|
||||
let mut t = FTable {
|
||||
rows: vec![vec![Cell { rowspan: 2, ..Default::default() }; n], vec![Cell::default(); n]],
|
||||
widths: Vec::new(),
|
||||
borderless: false,
|
||||
};
|
||||
let start = std::time::Instant::now();
|
||||
t.insert_covered();
|
||||
assert!(start.elapsed() < std::time::Duration::from_secs(10), "{:?}", start.elapsed());
|
||||
assert_eq!(t.rows[1].len(), n, "a full row takes no covered cell");
|
||||
assert!(t.rows[1].iter().all(|c| !c.covered));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn base64_round_trip() {
|
||||
for data in [&b""[..], b"f", b"fo", b"foo", b"foob", b"fooba", b"foobar", &[0, 255, 128, 7]] {
|
||||
|
||||
@@ -418,6 +418,11 @@ impl FTable {
|
||||
return;
|
||||
}
|
||||
let Some(row) = self.rows.get_mut(r + k) else { break };
|
||||
// A full row takes no covered cell: checked before it is walked, so a
|
||||
// wide row isn't scanned for every span above it.
|
||||
if row.len() >= 64 {
|
||||
continue;
|
||||
}
|
||||
// Find the index in that row at grid column `g`.
|
||||
let mut x = 0usize;
|
||||
let mut at = row.len();
|
||||
@@ -428,9 +433,7 @@ impl FTable {
|
||||
}
|
||||
x += cc.colspan.clamp(1, 63) as usize;
|
||||
}
|
||||
if row.len() < 64 {
|
||||
row.insert(at, Cell { colspan: span as u32, covered: true, ..Default::default() });
|
||||
}
|
||||
row.insert(at, Cell { colspan: span as u32, covered: true, ..Default::default() });
|
||||
}
|
||||
}
|
||||
g += span;
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
use std::borrow::Cow;
|
||||
|
||||
use super::date::{DateKind, builtin_date, custom_date, iso_datetime, serial_date};
|
||||
use super::{
|
||||
BTreeMap, Ev, Grid, HashMap, MAX_CELLS, MAX_COLS, MAX_ROWS, MAX_SHARED, MAX_SHEETS, MAX_XFS, Package, TextBudget, attr, push_capped, walk,
|
||||
@@ -263,7 +261,7 @@ pub(super) fn xlsx_rows(pkg: &mut Package<'_>, path: &str) -> Result<Vec<Vec<Str
|
||||
row.resize(c.col + 1, String::new());
|
||||
}
|
||||
if let Some(slot) = row.get_mut(c.col) {
|
||||
*slot = text.into_owned();
|
||||
*slot = text;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
@@ -276,15 +274,12 @@ pub(super) fn xlsx_rows(pkg: &mut Package<'_>, path: &str) -> Result<Vec<Vec<Str
|
||||
Ok(grid.rows)
|
||||
}
|
||||
|
||||
/// A cell's text: a shared string borrowed, so a cell the sheet then refuses (past the text
|
||||
/// budget, the columns or the rows) costs no copy of it.
|
||||
fn xlsx_value<'a>(c: &XCell, shared: &'a [String], formats: &[Option<DateKind>], date1904: bool) -> Cow<'a, str> {
|
||||
fn xlsx_value(c: &XCell, shared: &[String], formats: &[Option<DateKind>], date1904: bool) -> String {
|
||||
let v = c.value.trim();
|
||||
let kind = c.kind.trim();
|
||||
if kind.eq_ignore_ascii_case("s") {
|
||||
return Cow::Borrowed(v.parse::<usize>().ok().and_then(|i| shared.get(i)).map_or("", String::as_str));
|
||||
}
|
||||
Cow::Owned(if kind.eq_ignore_ascii_case("inlineStr") {
|
||||
v.parse::<usize>().ok().and_then(|i| shared.get(i)).cloned().unwrap_or_default()
|
||||
} else if kind.eq_ignore_ascii_case("inlineStr") {
|
||||
if c.inline.is_empty() { c.value.clone() } else { c.inline.clone() }
|
||||
} else if kind.eq_ignore_ascii_case("str") || kind.eq_ignore_ascii_case("e") {
|
||||
c.value.clone()
|
||||
@@ -295,12 +290,12 @@ fn xlsx_value<'a>(c: &XCell, shared: &'a [String], formats: &[Option<DateKind>],
|
||||
} else if v.is_empty() {
|
||||
c.inline.clone()
|
||||
} else {
|
||||
let Ok(x) = v.parse::<f64>() else { return Cow::Owned(v.to_string()) };
|
||||
let Ok(x) = v.parse::<f64>() else { return v.to_string() };
|
||||
match formats.get(c.style).copied().flatten() {
|
||||
Some(kind) => serial_date(x, date1904, kind).unwrap_or_else(|| number(x)),
|
||||
None => number(x),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// A number as a spreadsheet shows it in General format: up to 15 significant digits, no
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user