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