Skip to main content

sheets_diff/
lib.rs

1//! # sheets-diff
2//!
3//! Structured diff engine for Microsoft Excel `.xlsx` workbooks.
4//!
5//! ## Quick start
6//!
7//! ```rust,no_run
8//! use sheets_diff::compare_paths;
9//!
10//! let diff = compare_paths("old.xlsx", "new.xlsx")?;
11//! println!("changed cells: {}", diff.summary.cells_changed);
12//! # Ok::<(), sheets_diff::SheetsDiffError>(())
13//! ```
14//!
15//! ## Input sources
16//!
17//! | Function | When to use |
18//! |---|---|
19//! | [`compare_paths`] | Simplest; caller provides file paths |
20//! | [`compare_bytes`] | You already have the bytes (e.g. from a cache or repo) |
21//! | [`compare_readers`] | You have open `Read + Seek` handles |
22//! | `compare_*_with_options` variants | Any of the above plus [`DiffOptions`] |
23//!
24//! See [`DiffOptions`] / [`DiffOptionsBuilder`] for all configuration knobs.
25
26// ---------------------------------------------------------------------------
27// Internal modules (not pub)
28// ---------------------------------------------------------------------------
29
30pub mod address;
31mod diff;
32mod error;
33mod matcher;
34mod normalize;
35mod open;
36
37pub mod compare;
38
39// ---------------------------------------------------------------------------
40// Public modules
41// ---------------------------------------------------------------------------
42
43/// Typed result model (`WorkbookDiff`, `SheetDiff`, `CellDiff`, `CellValue`, …).
44pub mod model;
45
46/// Comparison options and builder (`DiffOptions`, `DiffOptionsBuilder`, …).
47pub mod options;
48
49/// Output formatters (text summary, unified diff).
50pub mod output;
51
52// ---------------------------------------------------------------------------
53// Re-exports — the stable public API surface (RFC-002, RFC-031)
54// ---------------------------------------------------------------------------
55
56// Error types
57pub use error::{LimitKind, OpenErrorKind, ReadErrorKind, SheetsDiffError};
58
59// Model
60pub use model::{
61    AlignmentSummary,
62    CellChangeKind,
63    CellDateTime,
64    CellDiff,
65    CellDuration,
66    CellError,
67    CellValue,
68    DateTimeKind,
69    DiagnosticKind,
70    DiagnosticLocation,
71    DiagnosticSummary,
72    Diagnostic,
73    DiffStage,
74    DiffSummary,
75    FormatChange,
76    FormulaChange,
77    FormulaText,
78    MatchConfidence,
79    Severity,
80    SheetChange,
81    SheetDiff,
82    SheetMatchReason,
83    SheetRef,
84    SheetSummary,
85    Side,
86    SourceDescription,
87    SourceKind,
88    ValueChange,
89    ValueDifferenceKind,
90    WorkbookChange,
91    WorkbookDiff,
92    WorkbookObjectChange,
93    WorkbookSideInfo,
94};
95
96// Address
97pub use address::{CellAddress, ComparedRange, MAX_COL, MAX_COL_LABEL, MAX_ROW};
98
99// Options
100pub use options::{
101    AlignmentMode,
102    Cancellation,
103    ComparisonOptions,
104    DateComparePolicy,
105    DiagnosticOptions,
106    DiffEvent,
107    DiffOptions,
108    DiffOptionsBuilder,
109    ExecutionMode,
110    ExecutionOptions,
111    FormulaCompareMode,
112    Limits,
113    MatchingOptions,
114    NumberComparePolicy,
115    NumericTypePolicy,
116    OutputOptions,
117    ProgressSink,
118    SheetMatchingMode,
119    TypeMismatchPolicy,
120    ValueCompareOptions,
121};
122
123// ---------------------------------------------------------------------------
124// Public entry points (RFC-033 §12)
125// ---------------------------------------------------------------------------
126
127use std::io::{Read, Seek};
128use std::path::Path;
129
130/// Compare two workbooks given their filesystem paths.
131///
132/// Uses [`DiffOptions::default()`].
133pub fn compare_paths(
134    old: impl AsRef<Path>,
135    new: impl AsRef<Path>,
136) -> Result<WorkbookDiff, SheetsDiffError> {
137    diff::run_compare_paths(old, new, DiffOptions::default())
138}
139
140/// Compare two workbooks given their filesystem paths, with explicit options.
141pub fn compare_paths_with_options(
142    old: impl AsRef<Path>,
143    new: impl AsRef<Path>,
144    opts: DiffOptions,
145) -> Result<WorkbookDiff, SheetsDiffError> {
146    diff::run_compare_paths(old, new, opts)
147}
148
149/// Compare two workbooks given byte slices.
150pub fn compare_bytes(
151    old: impl AsRef<[u8]>,
152    new: impl AsRef<[u8]>,
153) -> Result<WorkbookDiff, SheetsDiffError> {
154    diff::run_compare_bytes(old, new, DiffOptions::default())
155}
156
157/// Compare two workbooks given byte slices, with explicit options.
158pub fn compare_bytes_with_options(
159    old: impl AsRef<[u8]>,
160    new: impl AsRef<[u8]>,
161    opts: DiffOptions,
162) -> Result<WorkbookDiff, SheetsDiffError> {
163    diff::run_compare_bytes(old, new, opts)
164}
165
166/// Compare two workbooks given `Read + Seek` readers.
167///
168/// `.xlsx` is ZIP-based and requires seeking.
169pub fn compare_readers<R1, R2>(
170    old: R1,
171    new: R2,
172) -> Result<WorkbookDiff, SheetsDiffError>
173where
174    R1: Read + Seek,
175    R2: Read + Seek,
176{
177    diff::run_compare_readers(old, new, DiffOptions::default())
178}
179
180/// Compare two workbooks given `Read + Seek` readers, with explicit options.
181pub fn compare_readers_with_options<R1, R2>(
182    old: R1,
183    new: R2,
184    opts: DiffOptions,
185) -> Result<WorkbookDiff, SheetsDiffError>
186where
187    R1: Read + Seek,
188    R2: Read + Seek,
189{
190    diff::run_compare_readers(old, new, opts)
191}