use crate::{Cell, Module, Options, Result};
use std::cmp;
mod csv;
mod excel;
mod file_backer_upper;
mod google_sheets;
mod open_document;
pub(crate) use crate::target::csv::Csv;
pub(crate) use excel::Excel;
pub(crate) use google_sheets::GoogleSheets;
pub(crate) use open_document::OpenDocument;
#[derive(Clone, Debug, PartialEq)]
pub(crate) enum ExistingCell<V: Clone> {
Value(V),
Empty,
}
#[derive(Clone, Debug, Default, PartialEq)]
pub(crate) struct ExistingValues<V: Clone> {
cells: Vec<Vec<ExistingCell<V>>>,
}
pub trait CompilationTarget {
fn write_backup(&self) -> Result<()>;
fn write(&self, module: &Module) -> Result<()>;
}
#[derive(Clone, Debug, PartialEq)]
pub(crate) enum MergeResult<V: Clone> {
Existing(V),
New(Cell),
Empty,
}
fn merge_rows<V: Clone>(
existing_row: &[ExistingCell<V>],
module_row: &[Cell],
options: &Options,
) -> Vec<MergeResult<V>> {
(0..cmp::max(existing_row.len(), module_row.len()))
.map(|i| {
merge_cell(
existing_row.get(i).unwrap_or(&ExistingCell::Empty),
module_row.get(i),
options,
)
})
.collect()
}
fn merge_cell<V: Clone>(
existing: &ExistingCell<V>,
new: Option<&Cell>,
options: &Options,
) -> MergeResult<V> {
if let Some(new_val) = new {
match existing {
ExistingCell::Value(v) => {
if options.overwrite_values {
MergeResult::New(new_val.clone())
} else {
MergeResult::Existing(v.clone())
}
}
ExistingCell::Empty => MergeResult::New(new_val.clone()),
}
} else {
match existing {
ExistingCell::Value(v) => MergeResult::Existing(v.clone()),
ExistingCell::Empty => MergeResult::Empty,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
fn build_options(overwrite_values: bool) -> Options {
Options {
overwrite_values,
..Default::default()
}
}
#[test]
fn merge_rows_different_lengths() {
let options = build_options(false);
let existing = vec![
ExistingCell::Value(1),
ExistingCell::Value(2),
ExistingCell::Value(3),
];
let new = vec![Cell {
value: "new value".to_string(),
..Default::default()
}];
let merged_row = merge_rows(existing.as_slice(), &new, &options);
assert_eq!(3, merged_row.len());
}
#[test]
fn merge_rows_overwrite_false() {
let options = build_options(false);
assert_eq!(
MergeResult::Empty,
merge_cell(&ExistingCell::<usize>::Empty, None, &options)
);
assert_eq!(
MergeResult::Existing(1),
merge_cell(&ExistingCell::Value(1), None, &options)
);
let cell = Cell {
value: "new value".to_string(),
..Default::default()
};
assert_eq!(
MergeResult::Existing(1),
merge_cell(&ExistingCell::Value(1), Some(&cell), &options)
);
}
#[test]
fn merge_cell_overwrite_true() {
let options = build_options(true);
assert_eq!(
MergeResult::Empty,
merge_cell(&ExistingCell::<usize>::Empty, None, &options)
);
assert_eq!(
MergeResult::Existing(1),
merge_cell(&ExistingCell::Value(1), None, &options)
);
let cell = Cell {
value: "new value".to_string(),
..Default::default()
};
assert_eq!(
MergeResult::New(cell.clone()),
merge_cell(&ExistingCell::Value(1), Some(&cell), &options)
);
}
}