1 //! Rust Excel/OpenDocument reader
2 //!
3 //! # Status
4 //!
5 //! **calamine** is a pure Rust library to read Excel and OpenDocument Spreadsheet files.
6 //!
7 //! Read both cell values and vba project.
8 //!
9 //! # Examples
10 //! ```
11 //! use calamine::{Reader, open_workbook, Xlsx, DataType};
12 //!
13 //! // opens a new workbook
14 //! # let path = format!("{}/tests/issue3.xlsm", env!("CARGO_MANIFEST_DIR"));
15 //! let mut workbook: Xlsx<_> = open_workbook(path).expect("Cannot open file");
16 //!
17 //! // Read whole worksheet data and provide some statistics
18 //! if let Some(Ok(range)) = workbook.worksheet_range("Sheet1") {
19 //! let total_cells = range.get_size().0 * range.get_size().1;
20 //! let non_empty_cells: usize = range.used_cells().count();
21 //! println!("Found {} cells in 'Sheet1', including {} non empty cells",
22 //! total_cells, non_empty_cells);
23 //! // alternatively, we can manually filter rows
24 //! assert_eq!(non_empty_cells, range.rows()
25 //! .flat_map(|r| r.iter().filter(|&c| c != &DataType::Empty)).count());
26 //! }
27 //!
28 //! // Check if the workbook has a vba project
29 //! if let Some(Ok(mut vba)) = workbook.vba_project() {
30 //! let vba = vba.to_mut();
31 //! let module1 = vba.get_module("Module 1").unwrap();
32 //! println!("Module 1 code:");
33 //! println!("{}", module1);
34 //! for r in vba.get_references() {
35 //! if r.is_missing() {
36 //! println!("Reference {} is broken or not accessible", r.name);
37 //! }
38 //! }
39 //! }
40 //!
41 //! // You can also get defined names definition (string representation only)
42 //! for name in workbook.defined_names() {
43 //! println!("name: {}, formula: {}", name.0, name.1);
44 //! }
45 //!
46 //! // Now get all formula!
47 //! let sheets = workbook.sheet_names().to_owned();
48 //! for s in sheets {
49 //! println!("found {} formula in '{}'",
50 //! workbook
51 //! .worksheet_formula(&s)
52 //! .expect("sheet not found")
53 //! .expect("error while getting formula")
54 //! .rows().flat_map(|r| r.iter().filter(|f| !f.is_empty()))
55 //! .count(),
56 //! s);
57 //! }
58 //! ```
59 #![deny(missing_docs)]
60
61 #[macro_use]
62 mod utils;
63
64 mod auto;
65 mod cfb;
66 mod datatype;
67 mod ods;
68 mod xls;
69 mod xlsb;
70 mod xlsx;
71
72 mod de;
73 mod errors;
74 pub mod vba;
75
76 use serde::de::DeserializeOwned;
77 use std::borrow::Cow;
78 use std::cmp::{max, min};
79 use std::fmt;
80 use std::fs::File;
81 use std::io::{BufReader, Read, Seek};
82 use std::ops::{Index, IndexMut};
83 use std::path::Path;
84
85 pub use crate::auto::{open_workbook_auto, Sheets};
86 pub use crate::datatype::DataType;
87 pub use crate::de::{DeError, RangeDeserializer, RangeDeserializerBuilder, ToCellDeserializer};
88 pub use crate::errors::Error;
89 pub use crate::ods::{Ods, OdsError};
90 pub use crate::xls::{Xls, XlsError};
91 pub use crate::xlsb::{Xlsb, XlsbError};
92 pub use crate::xlsx::{Xlsx, XlsxError};
93
94 use crate::vba::VbaProject;
95
96 // https://msdn.microsoft.com/en-us/library/office/ff839168.aspx
97 /// An enum to represent all different errors that can appear as
98 /// a value in a worksheet cell
99 #[derive(Debug, Clone, PartialEq)]
100 pub enum CellErrorType {
101 /// Division by 0 error
102 Div0,
103 /// Unavailable value error
104 NA,
105 /// Invalid name error
106 Name,
107 /// Null value error
108 Null,
109 /// Number error
110 Num,
111 /// Invalid cell reference error
112 Ref,
113 /// Value error
114 Value,
115 /// Getting data
116 GettingData,
117 }
118
119 impl fmt::Display for CellErrorType {
fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error>120 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
121 match *self {
122 CellErrorType::Div0 => write!(f, "#DIV/0!"),
123 CellErrorType::NA => write!(f, "#N/A"),
124 CellErrorType::Name => write!(f, "#NAME?"),
125 CellErrorType::Null => write!(f, "#NULL!"),
126 CellErrorType::Num => write!(f, "#NUM!"),
127 CellErrorType::Ref => write!(f, "#REF!"),
128 CellErrorType::Value => write!(f, "#VALUE!"),
129 CellErrorType::GettingData => write!(f, "#DATA!"),
130 }
131 }
132 }
133
134 /// Common file metadata
135 ///
136 /// Depending on file type, some extra information may be stored
137 /// in the Reader implementations
138 #[derive(Debug, Default)]
139 pub struct Metadata {
140 sheets: Vec<String>,
141 /// Map of sheet names/sheet path within zip archive
142 names: Vec<(String, String)>,
143 }
144
145 // FIXME `Reader` must only be seek `Seek` for `Xls::xls`. Because of the present API this limits
146 // the kinds of readers (other) data in formats can be read from.
147 /// A trait to share spreadsheets reader functions accross different `FileType`s
148 pub trait Reader: Sized {
149 /// Inner reader type
150 type RS: Read + Seek;
151 /// Error specific to file type
152 type Error: std::fmt::Debug + From<std::io::Error>;
153
154 /// Creates a new instance.
new(reader: Self::RS) -> Result<Self, Self::Error>155 fn new(reader: Self::RS) -> Result<Self, Self::Error>;
156 /// Gets `VbaProject`
vba_project(&mut self) -> Option<Result<Cow<'_, VbaProject>, Self::Error>>157 fn vba_project(&mut self) -> Option<Result<Cow<'_, VbaProject>, Self::Error>>;
158 /// Initialize
metadata(&self) -> &Metadata159 fn metadata(&self) -> &Metadata;
160 /// Read worksheet data in corresponding worksheet path
worksheet_range(&mut self, name: &str) -> Option<Result<Range<DataType>, Self::Error>>161 fn worksheet_range(&mut self, name: &str) -> Option<Result<Range<DataType>, Self::Error>>;
162 /// Read worksheet formula in corresponding worksheet path
worksheet_formula(&mut self, _: &str) -> Option<Result<Range<String>, Self::Error>>163 fn worksheet_formula(&mut self, _: &str) -> Option<Result<Range<String>, Self::Error>>;
164
165 /// Get all sheet names of this workbook, in workbook order
166 ///
167 /// # Examples
168 /// ```
169 /// use calamine::{Xlsx, open_workbook, Reader};
170 ///
171 /// # let path = format!("{}/tests/issue3.xlsm", env!("CARGO_MANIFEST_DIR"));
172 /// let mut workbook: Xlsx<_> = open_workbook(path).unwrap();
173 /// println!("Sheets: {:#?}", workbook.sheet_names());
174 /// ```
sheet_names(&self) -> &[String]175 fn sheet_names(&self) -> &[String] {
176 &self.metadata().sheets
177 }
178
179 /// Get all defined names (Ranges names etc)
defined_names(&self) -> &[(String, String)]180 fn defined_names(&self) -> &[(String, String)] {
181 &self.metadata().names
182 }
183
184 /// Get the nth worksheet. Shortcut for getting the nth
185 /// sheet_name, then the corresponding worksheet.
worksheet_range_at(&mut self, n: usize) -> Option<Result<Range<DataType>, Self::Error>>186 fn worksheet_range_at(&mut self, n: usize) -> Option<Result<Range<DataType>, Self::Error>> {
187 let name = self.sheet_names().get(n)?.to_string();
188 self.worksheet_range(&name)
189 }
190 }
191
192 /// Convenient function to open a file with a BufReader<File>
open_workbook<R, P>(path: P) -> Result<R, R::Error> where R: Reader<RS = BufReader<File>>, P: AsRef<Path>,193 pub fn open_workbook<R, P>(path: P) -> Result<R, R::Error>
194 where
195 R: Reader<RS = BufReader<File>>,
196 P: AsRef<Path>,
197 {
198 let file = BufReader::new(File::open(path)?);
199 R::new(file)
200 }
201
202 /// A trait to constrain cells
203 pub trait CellType: Default + Clone + PartialEq {}
204 impl<T: Default + Clone + PartialEq> CellType for T {}
205
206 /// A struct to hold cell position and value
207 #[derive(Debug, Clone)]
208 pub struct Cell<T: CellType> {
209 /// Position for the cell (row, column)
210 pos: (u32, u32),
211 /// Value for the cell
212 val: T,
213 }
214
215 impl<T: CellType> Cell<T> {
216 /// Creates a new `Cell`
new(position: (u32, u32), value: T) -> Cell<T>217 pub fn new(position: (u32, u32), value: T) -> Cell<T> {
218 Cell {
219 pos: position,
220 val: value,
221 }
222 }
223
224 /// Gets `Cell` position
get_position(&self) -> (u32, u32)225 pub fn get_position(&self) -> (u32, u32) {
226 self.pos
227 }
228
229 /// Gets `Cell` value
get_value(&self) -> &T230 pub fn get_value(&self) -> &T {
231 &self.val
232 }
233 }
234
235 /// A struct which represents a squared selection of cells
236 #[derive(Debug, Default, Clone)]
237 pub struct Range<T: CellType> {
238 start: (u32, u32),
239 end: (u32, u32),
240 inner: Vec<T>,
241 }
242
243 impl<T: CellType> Range<T> {
244 /// Creates a new non-empty `Range`
245 ///
246 /// When possible, prefer the more efficient `Range::from_sparse`
247 ///
248 /// # Panics
249 ///
250 /// Panics if start.0 > end.0 or start.1 > end.1
251 #[inline]
new(start: (u32, u32), end: (u32, u32)) -> Range<T>252 pub fn new(start: (u32, u32), end: (u32, u32)) -> Range<T> {
253 assert!(start <= end, "invalid range bounds");
254 Range {
255 start,
256 end,
257 inner: vec![T::default(); ((end.0 - start.0 + 1) * (end.1 - start.1 + 1)) as usize],
258 }
259 }
260
261 /// Creates a new empty range
262 #[inline]
empty() -> Range<T>263 pub fn empty() -> Range<T> {
264 Range {
265 start: (0, 0),
266 end: (0, 0),
267 inner: Vec::new(),
268 }
269 }
270
271 /// Get top left cell position (row, column)
272 #[inline]
start(&self) -> Option<(u32, u32)>273 pub fn start(&self) -> Option<(u32, u32)> {
274 if self.is_empty() {
275 None
276 } else {
277 Some(self.start)
278 }
279 }
280
281 /// Get bottom right cell position (row, column)
282 #[inline]
end(&self) -> Option<(u32, u32)>283 pub fn end(&self) -> Option<(u32, u32)> {
284 if self.is_empty() {
285 None
286 } else {
287 Some(self.end)
288 }
289 }
290
291 /// Get column width
292 #[inline]
width(&self) -> usize293 pub fn width(&self) -> usize {
294 if self.is_empty() {
295 0
296 } else {
297 (self.end.1 - self.start.1 + 1) as usize
298 }
299 }
300
301 /// Get column height
302 #[inline]
height(&self) -> usize303 pub fn height(&self) -> usize {
304 if self.is_empty() {
305 0
306 } else {
307 (self.end.0 - self.start.0 + 1) as usize
308 }
309 }
310
311 /// Get size in (height, width) format
312 #[inline]
get_size(&self) -> (usize, usize)313 pub fn get_size(&self) -> (usize, usize) {
314 (self.height(), self.width())
315 }
316
317 /// Is range empty
318 #[inline]
is_empty(&self) -> bool319 pub fn is_empty(&self) -> bool {
320 self.inner.is_empty()
321 }
322
323 /// Creates a `Range` from a coo sparse vector of `Cell`s.
324 ///
325 /// Coordinate list (COO) is the natural way cells are stored
326 /// Inner size is defined only by non empty.
327 ///
328 /// cells: `Vec` of non empty `Cell`s, sorted by row
329 ///
330 /// # Panics
331 ///
332 /// panics when a `Cell` row is lower than the first `Cell` row or
333 /// bigger than the last `Cell` row.
from_sparse(cells: Vec<Cell<T>>) -> Range<T>334 pub fn from_sparse(cells: Vec<Cell<T>>) -> Range<T> {
335 if cells.is_empty() {
336 Range::empty()
337 } else {
338 // search bounds
339 let row_start = cells.first().unwrap().pos.0;
340 let row_end = cells.last().unwrap().pos.0;
341 let mut col_start = std::u32::MAX;
342 let mut col_end = 0;
343 for c in cells.iter().map(|c| c.pos.1) {
344 if c < col_start {
345 col_start = c;
346 }
347 if c > col_end {
348 col_end = c
349 }
350 }
351 let width = col_end - col_start + 1;
352 let len = ((row_end - row_start + 1) * width) as usize;
353 let mut v = vec![T::default(); len];
354 v.shrink_to_fit();
355 for c in cells {
356 let idx = ((c.pos.0 - row_start) * width + (c.pos.1 - col_start)) as usize;
357 v[idx] = c.val;
358 }
359 Range {
360 start: (row_start, col_start),
361 end: (row_end, col_end),
362 inner: v,
363 }
364 }
365 }
366
367 /// Set inner value from absolute position
368 ///
369 /// # Remarks
370 ///
371 /// Will try to resize inner structure if the value is out of bounds.
372 /// For relative positions, use Index trait
373 ///
374 /// Try to avoid this method as much as possible and prefer initializing
375 /// the `Range` with `from_sparse` constructor.
376 ///
377 /// # Panics
378 ///
379 /// If absolute_position > Cell start
380 ///
381 /// # Examples
382 /// ```
383 /// use calamine::{Range, DataType};
384 ///
385 /// let mut range = Range::new((0, 0), (5, 2));
386 /// assert_eq!(range.get_value((2, 1)), Some(&DataType::Empty));
387 /// range.set_value((2, 1), DataType::Float(1.0));
388 /// assert_eq!(range.get_value((2, 1)), Some(&DataType::Float(1.0)));
389 /// ```
set_value(&mut self, absolute_position: (u32, u32), value: T)390 pub fn set_value(&mut self, absolute_position: (u32, u32), value: T) {
391 assert!(
392 self.start.0 <= absolute_position.0 && self.start.1 <= absolute_position.1,
393 "absolute_position out of bounds"
394 );
395
396 // check if we need to change range dimension (strangely happens sometimes ...)
397 match (
398 self.end.0 < absolute_position.0,
399 self.end.1 < absolute_position.1,
400 ) {
401 (false, false) => (), // regular case, position within bounds
402 (true, false) => {
403 let len = (absolute_position.0 - self.end.0 + 1) as usize * self.width();
404 self.inner.extend_from_slice(&vec![T::default(); len]);
405 self.end.0 = absolute_position.0;
406 }
407 // missing some rows
408 (e, true) => {
409 let height = if e {
410 (absolute_position.0 - self.start.0 + 1) as usize
411 } else {
412 self.height()
413 };
414 let width = (absolute_position.1 - self.start.1 + 1) as usize;
415 let old_width = self.width();
416 let mut data = Vec::with_capacity(width * height);
417 let empty = vec![T::default(); width - old_width];
418 for sce in self.inner.chunks(old_width) {
419 data.extend_from_slice(sce);
420 data.extend_from_slice(&empty);
421 }
422 data.extend_from_slice(&vec![T::default(); width * (height - self.height())]);
423 if e {
424 self.end = absolute_position
425 } else {
426 self.end.1 = absolute_position.1
427 }
428 self.inner = data;
429 } // missing some columns
430 }
431
432 let pos = (
433 absolute_position.0 - self.start.0,
434 absolute_position.1 - self.start.1,
435 );
436 let idx = pos.0 as usize * self.width() + pos.1 as usize;
437 self.inner[idx] = value;
438 }
439
440 /// Get cell value from **absolute position**.
441 ///
442 /// If the `absolute_position` is out of range, returns `None`, else returns the cell value.
443 /// The coordinate format is (row, column).
444 ///
445 /// # Warnings
446 ///
447 /// For relative positions, use Index trait
448 ///
449 /// # Remarks
450 ///
451 /// Absolute position is in *sheet* referential while relative position is in *range* referential.
452 ///
453 /// For instance if we consider range *C2:H38*:
454 /// - `(0, 0)` absolute is "A1" and thus this function returns `None`
455 /// - `(0, 0)` relative is "C2" and is returned by the `Index` trait (i.e `my_range[(0, 0)]`)
456 ///
457 /// # Examples
458 /// ```
459 /// use calamine::{Range, DataType};
460 ///
461 /// let range: Range<usize> = Range::new((1, 0), (5, 2));
462 /// assert_eq!(range.get_value((0, 0)), None);
463 /// assert_eq!(range[(0, 0)], 0);
464 /// ```
get_value(&self, absolute_position: (u32, u32)) -> Option<&T>465 pub fn get_value(&self, absolute_position: (u32, u32)) -> Option<&T> {
466 let p = absolute_position;
467 if p.0 >= self.start.0 && p.0 <= self.end.0 && p.1 >= self.start.1 && p.1 <= self.end.1 {
468 return self.get((
469 (absolute_position.0 - self.start.0) as usize,
470 (absolute_position.1 - self.start.1) as usize,
471 ));
472 }
473 None
474 }
475
476 /// Get cell value from **relative position**.
get(&self, relative_position: (usize, usize)) -> Option<&T>477 pub fn get(&self, relative_position: (usize, usize)) -> Option<&T> {
478 let (row, col) = relative_position;
479 self.inner.get(row * self.width() + col)
480 }
481
482 /// Get an iterator over inner rows
483 ///
484 /// # Examples
485 /// ```
486 /// use calamine::{Range, DataType};
487 ///
488 /// let range: Range<DataType> = Range::new((0, 0), (5, 2));
489 /// // with rows item row: &[DataType]
490 /// assert_eq!(range.rows().map(|r| r.len()).sum::<usize>(), 18);
491 /// ```
rows(&self) -> Rows<'_, T>492 pub fn rows(&self) -> Rows<'_, T> {
493 if self.inner.is_empty() {
494 Rows { inner: None }
495 } else {
496 let width = self.width();
497 Rows {
498 inner: Some(self.inner.chunks(width)),
499 }
500 }
501 }
502
503 /// Get an iterator over used cells only
used_cells(&self) -> UsedCells<'_, T>504 pub fn used_cells(&self) -> UsedCells<'_, T> {
505 UsedCells {
506 width: self.width(),
507 inner: self.inner.iter().enumerate(),
508 }
509 }
510
511 /// Get an iterator over all cells in this range
cells(&self) -> Cells<'_, T>512 pub fn cells(&self) -> Cells<'_, T> {
513 Cells {
514 width: self.width(),
515 inner: self.inner.iter().enumerate(),
516 }
517 }
518
519 /// Build a `RangeDeserializer` from this configuration.
520 ///
521 /// # Example
522 ///
523 /// ```
524 /// # use calamine::{Reader, Error, open_workbook, Xlsx, RangeDeserializerBuilder};
525 /// fn example() -> Result<(), Error> {
526 /// let path = format!("{}/tests/temperature.xlsx", env!("CARGO_MANIFEST_DIR"));
527 /// let mut workbook: Xlsx<_> = open_workbook(path)?;
528 /// let mut sheet = workbook.worksheet_range("Sheet1")
529 /// .ok_or(Error::Msg("Cannot find 'Sheet1'"))??;
530 /// let mut iter = sheet.deserialize()?;
531 ///
532 /// if let Some(result) = iter.next() {
533 /// let (label, value): (String, f64) = result?;
534 /// assert_eq!(label, "celsius");
535 /// assert_eq!(value, 22.2222);
536 ///
537 /// Ok(())
538 /// } else {
539 /// return Err(From::from("expected at least one record but got none"));
540 /// }
541 /// }
542 /// ```
deserialize<'a, D>(&'a self) -> Result<RangeDeserializer<'a, T, D>, DeError> where T: ToCellDeserializer<'a>, D: DeserializeOwned,543 pub fn deserialize<'a, D>(&'a self) -> Result<RangeDeserializer<'a, T, D>, DeError>
544 where
545 T: ToCellDeserializer<'a>,
546 D: DeserializeOwned,
547 {
548 RangeDeserializerBuilder::new().from_range(self)
549 }
550
551 /// Build a new `Range` out of this range
552 ///
553 /// # Remarks
554 ///
555 /// Cells within this range will be cloned, cells out of it will be set to Empty
556 ///
557 /// # Example
558 ///
559 /// ```
560 /// # use calamine::{Range, DataType};
561 ///
562 /// fn example() {
563 /// let mut a = Range::new((1, 1), (3, 3));
564 /// a.set_value((1, 1), DataType::Bool(true));
565 /// a.set_value((2, 2), DataType::Bool(true));
566 ///
567 /// let b = a.range((2, 2), (5, 5));
568 /// assert_eq!(b.get_value((2, 2)), Some(&DataType::Bool(true)));
569 /// assert_eq!(b.get_value((3, 3)), Some(&DataType::Empty));
570 ///
571 /// let c = a.range((0, 0), (2, 2));
572 /// assert_eq!(c.get_value((0, 0)), Some(&DataType::Empty));
573 /// assert_eq!(c.get_value((1, 1)), Some(&DataType::Bool(true)));
574 /// assert_eq!(c.get_value((2, 2)), Some(&DataType::Bool(true)));
575 /// }
range(&self, start: (u32, u32), end: (u32, u32)) -> Range<T>576 pub fn range(&self, start: (u32, u32), end: (u32, u32)) -> Range<T> {
577 let mut other = Range::new(start, end);
578 let (self_start_row, self_start_col) = self.start;
579 let (self_end_row, self_end_col) = self.end;
580 let (other_start_row, other_start_col) = other.start;
581 let (other_end_row, other_end_col) = other.end;
582
583 // copy data from self to other
584 let start_row = max(self_start_row, other_start_row);
585 let end_row = min(self_end_row, other_end_row);
586 let start_col = max(self_start_col, other_start_col);
587 let end_col = min(self_end_col, other_end_col);
588
589 if start_row > end_row || start_col > end_col {
590 return other;
591 }
592
593 let self_width = self.width();
594 let other_width = other.width();
595
596 // change referential
597 //
598 // we want to copy range: start_row..(end_row + 1)
599 // In self referencial it is (start_row - self_start_row)..(end_row + 1 - self_start_row)
600 let self_row_start = (start_row - self_start_row) as usize;
601 let self_row_end = (end_row + 1 - self_start_row) as usize;
602 let self_col_start = (start_col - self_start_col) as usize;
603 let self_col_end = (end_col + 1 - self_start_col) as usize;
604
605 let other_row_start = (start_row - other_start_row) as usize;
606 let other_row_end = (end_row + 1 - other_start_row) as usize;
607 let other_col_start = (start_col - other_start_col) as usize;
608 let other_col_end = (end_col + 1 - other_start_col) as usize;
609
610 {
611 let self_rows = self
612 .inner
613 .chunks(self_width)
614 .take(self_row_end)
615 .skip(self_row_start);
616
617 let other_rows = other
618 .inner
619 .chunks_mut(other_width)
620 .take(other_row_end)
621 .skip(other_row_start);
622
623 for (self_row, other_row) in self_rows.zip(other_rows) {
624 let self_cols = &self_row[self_col_start..self_col_end];
625 let other_cols = &mut other_row[other_col_start..other_col_end];
626 other_cols.clone_from_slice(self_cols);
627 }
628 }
629
630 other
631 }
632 }
633
634 impl<T: CellType> Index<usize> for Range<T> {
635 type Output = [T];
index(&self, index: usize) -> &[T]636 fn index(&self, index: usize) -> &[T] {
637 let width = self.width();
638 &self.inner[index * width..(index + 1) * width]
639 }
640 }
641
642 impl<T: CellType> Index<(usize, usize)> for Range<T> {
643 type Output = T;
index(&self, index: (usize, usize)) -> &T644 fn index(&self, index: (usize, usize)) -> &T {
645 let (height, width) = self.get_size();
646 assert!(index.1 < width && index.0 < height, "index out of bounds");
647 &self.inner[index.0 * width + index.1]
648 }
649 }
650
651 impl<T: CellType> IndexMut<usize> for Range<T> {
index_mut(&mut self, index: usize) -> &mut [T]652 fn index_mut(&mut self, index: usize) -> &mut [T] {
653 let width = self.width();
654 &mut self.inner[index * width..(index + 1) * width]
655 }
656 }
657
658 impl<T: CellType> IndexMut<(usize, usize)> for Range<T> {
index_mut(&mut self, index: (usize, usize)) -> &mut T659 fn index_mut(&mut self, index: (usize, usize)) -> &mut T {
660 let (height, width) = self.get_size();
661 assert!(index.1 < width && index.0 < height, "index out of bounds");
662 &mut self.inner[index.0 * width + index.1]
663 }
664 }
665
666 /// A struct to iterate over all cells
667 #[derive(Debug)]
668 pub struct Cells<'a, T: CellType> {
669 width: usize,
670 inner: std::iter::Enumerate<std::slice::Iter<'a, T>>,
671 }
672
673 impl<'a, T: 'a + CellType> Iterator for Cells<'a, T> {
674 type Item = (usize, usize, &'a T);
next(&mut self) -> Option<Self::Item>675 fn next(&mut self) -> Option<Self::Item> {
676 self.inner.next().map(|(i, v)| {
677 let row = i / self.width;
678 let col = i % self.width;
679 (row, col, v)
680 })
681 }
size_hint(&self) -> (usize, Option<usize>)682 fn size_hint(&self) -> (usize, Option<usize>) {
683 self.inner.size_hint()
684 }
685 }
686
687 impl<'a, T: 'a + CellType> DoubleEndedIterator for Cells<'a, T> {
next_back(&mut self) -> Option<Self::Item>688 fn next_back(&mut self) -> Option<Self::Item> {
689 self.inner.next_back().map(|(i, v)| {
690 let row = i / self.width;
691 let col = i % self.width;
692 (row, col, v)
693 })
694 }
695 }
696
697 impl<'a, T: 'a + CellType> ExactSizeIterator for Cells<'a, T> {}
698
699 /// A struct to iterate over used cells
700 #[derive(Debug)]
701 pub struct UsedCells<'a, T: CellType> {
702 width: usize,
703 inner: std::iter::Enumerate<std::slice::Iter<'a, T>>,
704 }
705
706 impl<'a, T: 'a + CellType> Iterator for UsedCells<'a, T> {
707 type Item = (usize, usize, &'a T);
next(&mut self) -> Option<Self::Item>708 fn next(&mut self) -> Option<Self::Item> {
709 self.inner
710 .by_ref()
711 .find(|&(_, v)| v != &T::default())
712 .map(|(i, v)| {
713 let row = i / self.width;
714 let col = i % self.width;
715 (row, col, v)
716 })
717 }
size_hint(&self) -> (usize, Option<usize>)718 fn size_hint(&self) -> (usize, Option<usize>) {
719 let (_, up) = self.inner.size_hint();
720 (0, up)
721 }
722 }
723
724 impl<'a, T: 'a + CellType> DoubleEndedIterator for UsedCells<'a, T> {
next_back(&mut self) -> Option<Self::Item>725 fn next_back(&mut self) -> Option<Self::Item> {
726 self.inner
727 .by_ref()
728 .rfind(|&(_, v)| v != &T::default())
729 .map(|(i, v)| {
730 let row = i / self.width;
731 let col = i % self.width;
732 (row, col, v)
733 })
734 }
735 }
736
737 /// An iterator to read `Range` struct row by row
738 #[derive(Debug)]
739 pub struct Rows<'a, T: CellType> {
740 inner: Option<std::slice::Chunks<'a, T>>,
741 }
742
743 impl<'a, T: 'a + CellType> Iterator for Rows<'a, T> {
744 type Item = &'a [T];
next(&mut self) -> Option<Self::Item>745 fn next(&mut self) -> Option<Self::Item> {
746 self.inner.as_mut().and_then(|c| c.next())
747 }
size_hint(&self) -> (usize, Option<usize>)748 fn size_hint(&self) -> (usize, Option<usize>) {
749 self.inner
750 .as_ref()
751 .map_or((0, Some(0)), |ch| ch.size_hint())
752 }
753 }
754
755 impl<'a, T: 'a + CellType> DoubleEndedIterator for Rows<'a, T> {
next_back(&mut self) -> Option<Self::Item>756 fn next_back(&mut self) -> Option<Self::Item> {
757 self.inner.as_mut().and_then(|c| c.next_back())
758 }
759 }
760
761 impl<'a, T: 'a + CellType> ExactSizeIterator for Rows<'a, T> {}
762