| 1 | package xlsx |
| 2 | |
| 3 | import "amadan.net/oficina/sheets/internal/sheets/calc" |
| 4 | |
| 5 | // CellError is an import failure that knows which cell it happened at. |
| 6 | // |
| 7 | // It exists because import runs as a background job whose error text |
| 8 | // reaches both the owner and platform-held logs (spec §2.4, §11), and |
| 9 | // the caller building that text needs the coordinate as DATA. Without a |
| 10 | // type, the only way to name the failing cell is to parse it back out |
| 11 | // of an error string — a fragile read that also tempts the caller into |
| 12 | // echoing the whole chain, which is the leak this package spends its |
| 13 | // error handling avoiding. |
| 14 | // |
| 15 | // Error() is safe by construction: it renders the operation and the |
| 16 | // coordinate and nothing else. The wrapped cause is reachable through |
| 17 | // Unwrap for errors.Is/As, so a sentinel still matches, but it is never |
| 18 | // part of this error's own text — a caller that prints a CellError |
| 19 | // cannot leak a cell's contents even by accident, which is a stronger |
| 20 | // guarantee than a caller that remembers not to. |
| 21 | type CellError struct { |
| 22 | // Ref is the A1-style coordinate: "B7". |
| 23 | Ref string |
| 24 | // Op is what was being attempted, phrased to read after "xlsx: " |
| 25 | // and before the coordinate: "cannot parse cell". |
| 26 | Op string |
| 27 | // err is the cause. Deliberately unexported and deliberately absent |
| 28 | // from Error(): it is the half that can carry content. |
| 29 | err error |
| 30 | } |
| 31 | |
| 32 | func (e *CellError) Error() string { return "xlsx: " + e.Op + " " + e.Ref } |
| 33 | |
| 34 | // Unwrap exposes the cause to errors.Is and errors.As without putting |
| 35 | // it in Error()'s text. |
| 36 | func (e *CellError) Unwrap() error { return e.err } |
| 37 | |
| 38 | // cellErr builds a CellError for a 0-based position. |
| 39 | func cellErr(op string, rowPos, colPos int, err error) error { |
| 40 | return &CellError{Ref: calc.A1(rowPos, colPos), Op: op, err: err} |
| 41 | } |
| 42 | |