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 align;
32mod diff;
33mod error;
34mod matcher;
35mod meta;
36mod normalize;
37mod open;
38
39pub mod compare;
40
41// ---------------------------------------------------------------------------
42// Public modules
43// ---------------------------------------------------------------------------
44
45/// Typed result model (`WorkbookDiff`, `SheetDiff`, `CellDiff`, `CellValue`, …).
46pub mod model;
47
48/// Comparison options and builder (`DiffOptions`, `DiffOptionsBuilder`, …).
49pub mod options;
50
51/// Output formatters (text summary, unified diff).
52pub mod output;
53
54// ---------------------------------------------------------------------------
55// Re-exports — the stable public API surface (RFC-002, RFC-031)
56// ---------------------------------------------------------------------------
57
58// Error types
59pub use error::{LimitKind, OpenErrorKind, ReadErrorKind, SheetsDiffError};
60
61// Model
62pub use model::{
63    AlignmentSummary,
64    CellChangeKind,
65    CellDateTime,
66    CellDiff,
67    CellDuration,
68    CellError,
69    CellValue,
70    DateTimeKind,
71    DiagnosticKind,
72    DiagnosticLocation,
73    DiagnosticSummary,
74    Diagnostic,
75    DiffStage,
76    DiffSummary,
77    FormatChange,
78    FormulaChange,
79    FormulaText,
80    MatchConfidence,
81    Severity,
82    SheetChange,
83    SheetDiff,
84    SheetMatchReason,
85    SheetRef,
86    SheetSummary,
87    Side,
88    SourceDescription,
89    SourceKind,
90    ValueChange,
91    ValueDifferenceKind,
92    WorkbookChange,
93    WorkbookDiff,
94    WorkbookObjectChange,
95    WorkbookSideInfo,
96};
97
98// Address
99pub use address::{CellAddress, ComparedRange, MAX_COL, MAX_COL_LABEL, MAX_ROW};
100
101// Options
102pub use options::{
103    AlignmentMode,
104    Cancellation,
105    ComparisonOptions,
106    DateComparePolicy,
107    DiagnosticOptions,
108    DiffEvent,
109    DiffOptions,
110    DiffOptionsBuilder,
111    ExecutionMode,
112    ExecutionOptions,
113    FormatCompareMode,
114    FormulaCompareMode,
115    Limits,
116    MatchingOptions,
117    NumberComparePolicy,
118    NumericTypePolicy,
119    OutputOptions,
120    ProgressSink,
121    SheetMatchingMode,
122    TypeMismatchPolicy,
123    ValueCompareOptions,
124};
125
126// ---------------------------------------------------------------------------
127// Public entry points (RFC-033 §12)
128// ---------------------------------------------------------------------------
129
130use std::io::{Read, Seek};
131use std::path::Path;
132
133/// Compare two workbooks given their filesystem paths.
134///
135/// Uses [`DiffOptions::default()`].
136pub fn compare_paths(
137    old: impl AsRef<Path>,
138    new: impl AsRef<Path>,
139) -> Result<WorkbookDiff, SheetsDiffError> {
140    diff::run_compare_paths(old, new, DiffOptions::default())
141}
142
143/// Compare two workbooks given their filesystem paths, with explicit options.
144pub fn compare_paths_with_options(
145    old: impl AsRef<Path>,
146    new: impl AsRef<Path>,
147    opts: DiffOptions,
148) -> Result<WorkbookDiff, SheetsDiffError> {
149    diff::run_compare_paths(old, new, opts)
150}
151
152/// Compare two workbooks given byte slices.
153pub fn compare_bytes(
154    old: impl AsRef<[u8]>,
155    new: impl AsRef<[u8]>,
156) -> Result<WorkbookDiff, SheetsDiffError> {
157    diff::run_compare_bytes(old, new, DiffOptions::default())
158}
159
160/// Compare two workbooks given byte slices, with explicit options.
161pub fn compare_bytes_with_options(
162    old: impl AsRef<[u8]>,
163    new: impl AsRef<[u8]>,
164    opts: DiffOptions,
165) -> Result<WorkbookDiff, SheetsDiffError> {
166    diff::run_compare_bytes(old, new, opts)
167}
168
169/// Compare two workbooks given `Read + Seek` readers.
170///
171/// `.xlsx` is ZIP-based and requires seeking.
172pub fn compare_readers<R1, R2>(
173    old: R1,
174    new: R2,
175) -> Result<WorkbookDiff, SheetsDiffError>
176where
177    R1: Read + Seek,
178    R2: Read + Seek,
179{
180    diff::run_compare_readers(old, new, DiffOptions::default())
181}
182
183/// Compare two workbooks given `Read + Seek` readers, with explicit options.
184pub fn compare_readers_with_options<R1, R2>(
185    old: R1,
186    new: R2,
187    opts: DiffOptions,
188) -> Result<WorkbookDiff, SheetsDiffError>
189where
190    R1: Read + Seek,
191    R2: Read + Seek,
192{
193    diff::run_compare_readers(old, new, opts)
194}