Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,16 +170,23 @@ pub struct Dimensions {
#[allow(clippy::len_without_is_empty)]
impl Dimensions {
/// create dimensions info with start position and end position
///
/// The corners may be given in either order; they are stored so that
/// `start <= end` on both axes.
Comment thread
krickert marked this conversation as resolved.
Outdated
pub fn new(start: (u32, u32), end: (u32, u32)) -> Self {
Self { start, end }
Self {
start: (start.0.min(end.0), start.1.min(end.1)),
end: (start.0.max(end.0), start.1.max(end.1)),
}
}
/// check if a position is in it
pub fn contains(&self, row: u32, col: u32) -> bool {
row >= self.start.0 && row <= self.end.0 && col >= self.start.1 && col <= self.end.1
}
/// len
pub fn len(&self) -> u64 {
(self.end.0 - self.start.0 + 1) as u64 * (self.end.1 - self.start.1 + 1) as u64
// Widened before the `+ 1` so a full-width axis cannot overflow.
(u64::from(self.end.0 - self.start.0) + 1) * (u64::from(self.end.1 - self.start.1) + 1)
}
}

Expand Down
65 changes: 55 additions & 10 deletions src/xlsx/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2789,18 +2789,21 @@ pub(crate) fn get_dimension(dimension: &[u8]) -> Result<Dimensions, XlsxError> {
end: parts[0],
}),
2 => {
let rows = parts[1].0 - parts[0].0;
let columns = parts[1].1 - parts[0].1;
if rows > MAX_ROWS {
warn!("xlsx has more than maximum number of rows ({rows} > {MAX_ROWS})");
// The `ref` may be in reversed order like `C5:A1`.
let dim = Dimensions::new(parts[0], parts[1]);
if dim.end.0 > MAX_ROWS {
warn!(
"xlsx has more than maximum number of rows ({} > {MAX_ROWS})",
Comment thread
krickert marked this conversation as resolved.
Outdated
dim.end.0
);
}
if columns > MAX_COLUMNS {
warn!("xlsx has more than maximum number of columns ({columns} > {MAX_COLUMNS})");
if dim.end.1 > MAX_COLUMNS {
warn!(
"xlsx has more than maximum number of columns ({} > {MAX_COLUMNS})",
dim.end.1
);
}
Ok(Dimensions {
start: parts[0],
end: parts[1],
})
Ok(dim)
}
len => Err(XlsxError::DimensionCount(len)),
}
Expand Down Expand Up @@ -4010,6 +4013,48 @@ mod tests {
);
}

#[test]
fn test_reversed_dimension_is_normalised() {
// A reversed `ref` such as `C5:A1` gives the same `Dimensions` as `A1:C5`.
let reversed = get_dimension(b"C5:A1").unwrap();
assert_eq!(
reversed,
Dimensions {
start: (0, 0),
end: (4, 2),
}
);
assert_eq!(reversed, get_dimension(b"A1:C5").unwrap());
assert_eq!(reversed.len(), 15);

// Reversed on one axis only.
assert_eq!(
get_dimension(b"A5:C1").unwrap(),
get_dimension(b"A1:C5").unwrap()
);
assert_eq!(
get_dimension(b"C1:A5").unwrap(),
get_dimension(b"A1:C5").unwrap()
);
}

#[test]
fn test_dimensions_new_normalises_order() {
let dim = Dimensions::new((4, 2), (0, 0));
assert_eq!(
dim,
Dimensions {
start: (0, 0),
end: (4, 2),
}
);
assert_eq!(dim.len(), 15);
// A single cell is still one cell, and a full-width axis does not
// overflow the `+ 1`.
assert_eq!(Dimensions::new((7, 7), (7, 7)).len(), 1);
assert_eq!(Dimensions::new((0, 0), (u32::MAX, 0)).len(), 4_294_967_296);
}

#[test]
fn test_parse_error() {
assert_eq!(
Expand Down
Loading