refactor(reader): extract.rs moves into ledger-reader (U0d)
D-61 (Q-9): the writer sheds the typesetter and the crate map is layered again. The PDF/XLSX reader (extract.rs, plan P6) is now the plain library crate ledger-reader, moved whole with git mv and no behavior change. ledger-store depends on it instead of ledger-import, so the store no longer builds Typst or the fonts; ledger-import re-exports it as ledger_import::extract so gui, mcp, host and the fuzz targets compile unchanged, and still never depends on the store. New crate carries only the dependencies extract.rs imports (hayro, hayro-interpret, kurbo, zip, quick-xml, thiserror); fuzz/Cargo.lock gains the new package. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HS8WZziDnyxunC23MUxrLp
This commit is contained in:
1 parent
f98471516e
commit
bb1eb84200
15 files changed
+344
-68
No files matched your search
@@ -160,7 +160,7 @@ clone, with status. Rules:
|
||||
`company.timezone`: "today" is computed by the caller and passed in;
|
||||
the core still reads no clock). New dependencies need justification in
|
||||
the commit message. No I/O, no networking, no time-source in the core.
|
||||
- Future crates (`ledger-store`, `ledger-import`, `ledger-oracle`, `books-app`)
|
||||
- Future crates (`ledger-store`, `ledger-import`, `ledger-reader`, `ledger-oracle`, `books-app`)
|
||||
depend inward toward the core, never the reverse. See `docs/architecture.md`.
|
||||
|
||||
## Working here
|
||||
|
||||
Generated
+14
-5
@@ -3989,13 +3989,10 @@ dependencies = [
|
||||
"chrono",
|
||||
"csv",
|
||||
"deunicode",
|
||||
"hayro 0.8.0",
|
||||
"hayro-interpret 0.8.0",
|
||||
"kurbo",
|
||||
"ledger-core",
|
||||
"ledger-reader",
|
||||
"proptest",
|
||||
"qrcode",
|
||||
"quick-xml 0.38.4",
|
||||
"rqrr",
|
||||
"rust_decimal",
|
||||
"rust_xlsxwriter",
|
||||
@@ -4058,6 +4055,18 @@ dependencies = [
|
||||
"zip 9.0.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ledger-reader"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"hayro 0.8.0",
|
||||
"hayro-interpret 0.8.0",
|
||||
"kurbo",
|
||||
"quick-xml 0.38.4",
|
||||
"thiserror 2.0.21",
|
||||
"zip 9.0.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ledger-store"
|
||||
version = "0.1.0"
|
||||
@@ -4068,7 +4077,7 @@ dependencies = [
|
||||
"getrandom 0.2.17",
|
||||
"hex",
|
||||
"ledger-core",
|
||||
"ledger-import",
|
||||
"ledger-reader",
|
||||
"libc",
|
||||
"proptest",
|
||||
"rusqlite",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
members = ["crates/ledger-core", "crates/ledger-store", "crates/ledger-config", "crates/ledger-mcp", "crates/ledger-import", "crates/ledger-cli", "crates/ledger-gui", "crates/ledger-vault", "crates/ledger-host", "crates/ledger-package"]
|
||||
members = ["crates/ledger-core", "crates/ledger-store", "crates/ledger-config", "crates/ledger-mcp", "crates/ledger-import", "crates/ledger-reader", "crates/ledger-cli", "crates/ledger-gui", "crates/ledger-vault", "crates/ledger-host", "crates/ledger-package"]
|
||||
|
||||
[workspace.package]
|
||||
edition = "2024"
|
||||
|
||||
@@ -18,17 +18,8 @@ typst = "0.15.1"
|
||||
serde_json = "1"
|
||||
typst-layout = "0.15.1"
|
||||
qrcode = { version = "0.14.1", default-features = false, features = ["svg"] }
|
||||
# Extraction (extract.rs, plan P6): a PDF's text, a page's pixels, an
|
||||
# XLSX's cells. hayro (the renderer) and hayro-interpret (the text
|
||||
# interpreter) are pure Rust and already the viewer's PDF reader, so the
|
||||
# server and the viewer read a receipt through one implementation rather
|
||||
# than two; `zip` and `quick-xml` read a spreadsheet's XML. None of them
|
||||
# touches money: a number is kept as the decimal string the XML holds.
|
||||
hayro = { version = "0.8", features = ["embed-fonts"] }
|
||||
hayro-interpret = "0.8"
|
||||
kurbo = "0.13"
|
||||
zip = { version = "9.0.1", default-features = false, features = ["deflate"] }
|
||||
quick-xml = "0.38"
|
||||
# The reader (extract.rs moved out: D-61); re-exported as `extract`.
|
||||
ledger-reader = { path = "../ledger-reader" }
|
||||
# BSD-3-Clause: the IIF's transliteration to ASCII (iif.rs, rules.md B-34).
|
||||
# Pinned exactly: a new table would change what a CPA's file says.
|
||||
deunicode = { version = "=1.6.0", default-features = false }
|
||||
@@ -38,4 +29,5 @@ workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
proptest = "1"
|
||||
zip = { version = "9.0.1", default-features = false, features = ["deflate"] }
|
||||
rqrr = { version = "0.11.0", default-features = false }
|
||||
@@ -16,7 +16,8 @@
|
||||
pub mod asset_register;
|
||||
pub mod bank_csv;
|
||||
pub mod chart_csv;
|
||||
pub mod extract;
|
||||
/// The one reader, now the `ledger-reader` crate (D-61), kept at its old path.
|
||||
pub use ledger_reader as extract;
|
||||
pub mod fonts;
|
||||
pub mod iif;
|
||||
pub mod invoice_pdf;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//! The one extractor (plan P6 step 1): a PDF's text and pages, and an
|
||||
//! XLSX's cells as exact decimal strings.
|
||||
//!
|
||||
//! Expected behavior comes from `crates/ledger-import/src/extract.rs`'s
|
||||
//! Expected behavior comes from `crates/ledger-reader/src/lib.rs`'s
|
||||
//! INVARIANTS, which come from plan/served.md P6 step 1 and D-15, D-32 and
|
||||
//! D-53.
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
[package]
|
||||
name = "ledger-reader"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
license = "MIT OR Apache-2.0"
|
||||
description = "The one reader: a PDF's text and pages, an XLSX's cells as exact decimal strings (plan P6, D-61)."
|
||||
|
||||
[dependencies]
|
||||
thiserror = "2"
|
||||
# Extraction (plan P6): a PDF's text, a page's pixels, an XLSX's cells.
|
||||
# hayro (the renderer) and hayro-interpret (the text interpreter) are pure
|
||||
# Rust and already the viewer's PDF reader, so the server and the viewer
|
||||
# read a receipt through one implementation rather than two; `zip` and
|
||||
# `quick-xml` read a spreadsheet's XML. None of them touches money: a
|
||||
# number is kept as the decimal string the XML holds.
|
||||
hayro = { version = "0.8", features = ["embed-fonts"] }
|
||||
hayro-interpret = "0.8"
|
||||
kurbo = "0.13"
|
||||
zip = { version = "9.0.1", default-features = false, features = ["deflate"] }
|
||||
quick-xml = "0.38"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
File renamed without changes.
@@ -8,11 +8,11 @@ description = "Durable persistence for wanderbooks: a hash-chained JSONL journal
|
||||
|
||||
[dependencies]
|
||||
ledger-core = { path = "../ledger-core" }
|
||||
# The one extractor (plan P6 step 1, D-53): the writer journals a file's
|
||||
# The one reader (plan P6 step 1, D-53, D-61: its own crate): the writer journals a file's
|
||||
# text at attach time and on `wanderbooks books extract`, so the extractor
|
||||
# must be callable here rather than only from the server. It is pure and
|
||||
# deterministic (no I/O, no network, no time source).
|
||||
ledger-import = { path = "../ledger-import" }
|
||||
ledger-reader = { path = "../ledger-reader" }
|
||||
rusqlite = { version = "0.32", features = ["bundled"] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
|
||||
@@ -45,7 +45,7 @@ use ledger_core::{
|
||||
payroll::{PayrollAccounts, payroll_entry_plan, payroll_remit_plan},
|
||||
reports,
|
||||
};
|
||||
use ledger_import::extract::{EXTRACTOR as E_EXTRACTOR, VERSION as E_VERSION};
|
||||
use ledger_reader::{EXTRACTOR as E_EXTRACTOR, VERSION as E_VERSION};
|
||||
use rusqlite::{Connection, OptionalExtension, params};
|
||||
use rust_decimal::Decimal;
|
||||
use serde_json::{Value, json};
|
||||
@@ -368,7 +368,7 @@ pub struct Extraction {
|
||||
pub attachment_id: u64,
|
||||
/// The text's blob (its SHA-256), when there is text.
|
||||
pub text_sha256: Option<String>,
|
||||
/// What read it (`ledger_import::extract::EXTRACTOR`).
|
||||
/// What read it (`ledger_reader::EXTRACTOR`).
|
||||
pub extractor: String,
|
||||
/// That extractor's version.
|
||||
pub version: String,
|
||||
@@ -4620,7 +4620,7 @@ impl Store {
|
||||
if let Some(already) = self.extraction_for(attachment_id, E_EXTRACTOR, E_VERSION)? {
|
||||
return Ok(already);
|
||||
}
|
||||
let got = ledger_import::extract::extract(bytes, mime_type, file_name);
|
||||
let got = ledger_reader::extract(bytes, mime_type, file_name);
|
||||
let text_sha = match &got.text {
|
||||
Some(text) => Some(self.blobs.put(text.as_bytes())?.0),
|
||||
None => None,
|
||||
@@ -4644,9 +4644,9 @@ impl Store {
|
||||
version: E_VERSION.into(),
|
||||
pages: got.pages,
|
||||
status: match got.status {
|
||||
ledger_import::extract::ExtractStatus::Ok => ExtractionStatus::Ok,
|
||||
ledger_import::extract::ExtractStatus::None => ExtractionStatus::None,
|
||||
ledger_import::extract::ExtractStatus::Failed => ExtractionStatus::Failed,
|
||||
ledger_reader::ExtractStatus::Ok => ExtractionStatus::Ok,
|
||||
ledger_reader::ExtractStatus::None => ExtractionStatus::None,
|
||||
ledger_reader::ExtractStatus::Failed => ExtractionStatus::Failed,
|
||||
},
|
||||
seq: line.seq,
|
||||
})
|
||||
|
||||
@@ -1471,8 +1471,8 @@ fn extraction_is_journaled_once_per_version() {
|
||||
let x = s.extraction(id).unwrap().expect("an extraction record");
|
||||
assert_eq!(x.status, ExtractionStatus::Ok);
|
||||
assert_eq!(x.pages, 1);
|
||||
assert_eq!(x.extractor, ledger_import::extract::EXTRACTOR);
|
||||
assert_eq!(x.version, ledger_import::extract::VERSION);
|
||||
assert_eq!(x.extractor, ledger_reader::EXTRACTOR);
|
||||
assert_eq!(x.version, ledger_reader::VERSION);
|
||||
assert_eq!(
|
||||
s.extraction_text(id).unwrap().as_deref(),
|
||||
Some(String::from_utf8_lossy(text).as_ref())
|
||||
|
||||
+14
-14
@@ -31,8 +31,9 @@ the specification in `bookspec/` (which never depends on the engine).
|
||||
| `ledger-core` | the semantics engine: money, chart, journal, `Ledger` commands, reports, periods, assets, schedules, parties, A/R and A/P, payroll, projects, settings and conventions, the kernel and its Kani harnesses | nothing |
|
||||
| `ledger-vault` | the TIN vault: XChaCha20-Poly1305 records under the book's key | nothing |
|
||||
| `ledger-config` | the `wanderbooks.toml` codec (adoption in, `books.export_settings` out) and the receipt policy until P4 moves it into the core | `ledger-core` |
|
||||
| `ledger-store` | the source of truth: the hash-chained JSONL journal, its format gate, the SQLite projection (schema 18; a file per schema), the blob store, backups, the access log, `Snapshot` for readers | `ledger-core`, `ledger-import` (the file reader, P6; `ledger-reader` after U0d, D-61) |
|
||||
| `ledger-import` | formats: QuickBooks CSV in; IIF, XLSX, Typst PDFs (statements, the invoice, labels) out | `ledger-core` |
|
||||
| `ledger-store` | the source of truth: the hash-chained JSONL journal, its format gate, the SQLite projection (schema 18; a file per schema), the blob store, backups, the access log, `Snapshot` for readers | `ledger-core`, `ledger-reader` (P6, D-61) |
|
||||
| `ledger-reader` | the one reader: a PDF's text and pages, an XLSX's cells as exact decimal strings, plain text (P6; a plain library, in-process, D-61); `ledger-import` re-exports it as `extract` | none (`hayro`, `zip`, `quick-xml`) |
|
||||
| `ledger-import` | formats: QuickBooks CSV in; IIF, XLSX, Typst PDFs (statements, the invoice, labels) out | `ledger-core`, `ledger-reader` |
|
||||
| `ledger-package` | the shared read-only view over `Store` or `Snapshot` (`PackageBooks`): the CPA package, the 1099 worksheet, the invoice document, Needs attention | `ledger-core`, `ledger-store`, `ledger-config`, `ledger-import`, `ledger-vault` |
|
||||
| `ledger-mcp` | the books server: the MCP tools (122), resources, the handbook, scopes, the door and the access log, backups' scheduling | all of the above |
|
||||
| `ledger-host` | the host and its leases, the agent bridge (`wanderbooks mcp`), tokens in the OS keyring, the owner's commands, uploads and downloads | `ledger-store`, `ledger-mcp`, `ledger-config` |
|
||||
@@ -50,14 +51,13 @@ test `crates/ledger-core/tests/oracle_gnucash.rs` with `oracle/gnucash/`
|
||||
(`PackageBooks` is the shared view; extraction is in-process in
|
||||
`ledger-import`, P6).
|
||||
|
||||
Decided (Q-9 → D-61, 2026-10-29): P6 made `ledger-store` depend on
|
||||
`ledger-import` so the writer can extract a file's text at attach time
|
||||
and on the backfill command. That keeps the direction inward
|
||||
(`ledger-import` depends on the core alone and must never depend on the
|
||||
store) but pulls Typst, the fonts and hayro into the store's dependency
|
||||
closure. Unit U0d (plan 8.2, after S4.5) moves the reader into a small
|
||||
library crate, `ledger-reader`, that both depend on; until it lands the
|
||||
arrow stands as drawn above.
|
||||
Decided and done (Q-9 → D-61, unit U0d): P6 had made `ledger-store` depend
|
||||
on `ledger-import` so the writer can extract a file's text at attach time,
|
||||
which pulled Typst, the fonts and hayro into the store's dependency
|
||||
closure. The reader now lives in the small library crate `ledger-reader`;
|
||||
`ledger-store` and `ledger-import` both depend on it (`ledger-import`
|
||||
re-exports it as `extract`), the store no longer builds the typesetter,
|
||||
and `ledger-import` still never depends on the store.
|
||||
|
||||
`ledger-core` itself (`crates/ledger-core/src/`): `money`, `account`,
|
||||
`journal`, `ledger` (the command surface and replay), `kernel` (every
|
||||
@@ -117,13 +117,13 @@ the agent's cannot drift apart. The crate depends inward (`ledger-core`,
|
||||
`ledger-store`, `ledger-config`, `ledger-import`, `ledger-vault`), never on
|
||||
`ledger-mcp` or `ledger-gui`.
|
||||
|
||||
## The evidence pipeline (`ledger-import`, `ledger-core`, `ledger-store`, P6)
|
||||
## The evidence pipeline (`ledger-reader`, `ledger-core`, `ledger-store`, P6)
|
||||
|
||||
One extractor lives in `ledger-import` (`src/extract.rs`, D-53: in-process,
|
||||
no new crate): a PDF's text and pages, an XLSX's cells as exact decimal
|
||||
One extractor lives in `ledger-reader` (`src/lib.rs`, D-53, D-61: in-process,
|
||||
a plain library): a PDF's text and pages, an XLSX's cells as exact decimal
|
||||
strings, and plain text; the caps are 25 MiB in, 30 pages and 2 MiB of
|
||||
text, and a reader panic is caught there. `ledger-store` depends on
|
||||
`ledger-import` so the writer can read a file as it is filed and journal
|
||||
`ledger-reader` so the writer can read a file as it is filed and journal
|
||||
`attachment.text_extracted` (content-addressed text blob, extractor,
|
||||
version, pages, `ok`/`none`/`failed`), one record per attachment, extractor
|
||||
and version; `Store::verify` checks the text blob's hash and never
|
||||
|
||||
+4
-4
@@ -3273,8 +3273,8 @@ check, and the preview's clone; attention's year comparison and its
|
||||
## P6: the evidence pipeline (2026-10-27)
|
||||
|
||||
Extraction, dedup, annotations and company record categories (plan P6;
|
||||
rules.md B-44). One in-process extractor in `ledger-import`
|
||||
(`src/extract.rs`): `pdf_text` and `pdf_lines` (promoted from the PDF
|
||||
rules.md B-44). One in-process extractor in `ledger-reader`
|
||||
(`crates/ledger-reader/src/lib.rs`): `pdf_text` and `pdf_lines` (promoted from the PDF
|
||||
reader test), `page_count`, `page_png` (promoted from the viewer's private
|
||||
rasterizer), `xlsx_text` (cells as the exact decimal strings the sheet XML
|
||||
holds), `text_of` (moved from `tin_files`, now reading a PDF's text too)
|
||||
@@ -3284,13 +3284,13 @@ reaching the server (D-32: no sandbox, and the plan says so). The viewer
|
||||
and the server's filing scan both read through it: `ledger-gui/src/receipts.rs`
|
||||
keeps no `hayro` use of its own.
|
||||
|
||||
- **ledger-import:** `tests/extract.rs` `extraction_deterministic` (same
|
||||
- **ledger-reader (tests stay in `crates/ledger-import/tests/extract.rs`, which builds its PDFs with `ledger-import`):** `extraction_deterministic` (same
|
||||
bytes, same text and PNG bytes; plain text and an image's `none`),
|
||||
`xlsx_cells_are_decimal_strings` (proptest: the cell text is the decimal
|
||||
string written, never a float), `a_pdf_that_crashes_the_reader_is_failed_not_fatal`
|
||||
(garbage and truncated PDFs are `Err`, the too-large cap is refused
|
||||
before the reader, page 31 and a zero-size page are refused); unit tests
|
||||
in `src/extract.rs` for the panic catch and the input cap. `tests/spec_import.rs`
|
||||
in `crates/ledger-reader/src/lib.rs` for the panic catch and the input cap. `tests/spec_import.rs`
|
||||
keeps its script/RTL PDF test; its `pdf_lines` helper is now the
|
||||
extractor's.
|
||||
- **ledger-core:** `src/evidence.rs` (`Annotation`, `AnnotationFields`;
|
||||
|
||||
Generated
+270
-19
@@ -29,6 +29,21 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "alloc-no-stdlib"
|
||||
version = "2.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3"
|
||||
|
||||
[[package]]
|
||||
name = "alloc-stdlib"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e76a019e91224d279006ff972f1e984179a6e9feb050adba6ce8274aef23195"
|
||||
dependencies = [
|
||||
"alloc-no-stdlib",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.6"
|
||||
@@ -223,6 +238,27 @@ dependencies = [
|
||||
"syn 3.0.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "brotli"
|
||||
version = "8.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5cc91aac060a7a1e25823bdccbfb6af1875b88f17c6daac97894eed8207166b3"
|
||||
dependencies = [
|
||||
"alloc-no-stdlib",
|
||||
"alloc-stdlib",
|
||||
"brotli-decompressor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "brotli-decompressor"
|
||||
version = "5.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a32acac15fe1967bc3986b2a6347dffc965602354ea6f450ad07e8bfd253583"
|
||||
dependencies = [
|
||||
"alloc-no-stdlib",
|
||||
"alloc-stdlib",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.20.3"
|
||||
@@ -753,6 +789,12 @@ version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b97b65636e5b9ef369943878ac74335ba1c55c1cb6adbf1e2c293c624248d693"
|
||||
|
||||
[[package]]
|
||||
name = "fearless_simd"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4beca3cb2444e3304ac30843cc091f44ed58932353cd492ce740067bfce6b12"
|
||||
|
||||
[[package]]
|
||||
name = "fearless_simd"
|
||||
version = "1.1.0"
|
||||
@@ -806,6 +848,15 @@ dependencies = [
|
||||
"bytemuck",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "font-types"
|
||||
version = "0.12.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "835ae9d781464a79026cde387f9cbc650c9a4909d7cf7e658b127e3c35d2f35d"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fontconfig-parser"
|
||||
version = "0.5.8"
|
||||
@@ -902,8 +953,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"r-efi 6.0.0",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -934,11 +987,28 @@ dependencies = [
|
||||
"log",
|
||||
"peniko",
|
||||
"png",
|
||||
"skrifa",
|
||||
"skrifa 0.42.1",
|
||||
"smallvec",
|
||||
"vello_common 0.0.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glifo"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f1218dedd5348c1b166ec3b8b3cbca49d2f527bd43b3fa072ea5123c523ed3f"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"foldhash",
|
||||
"hashbrown 0.17.1",
|
||||
"log",
|
||||
"peniko",
|
||||
"png",
|
||||
"skrifa 0.44.0",
|
||||
"smallvec",
|
||||
"vello_common 0.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "guillotiere"
|
||||
version = "0.7.0"
|
||||
@@ -1016,11 +1086,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4caa128ab87fd48ffb7490617cf93f77f606820dffbc9fd9ef6ab0ed077f56d"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"hayro-interpret",
|
||||
"hayro-interpret 0.7.0",
|
||||
"image",
|
||||
"kurbo",
|
||||
"pic-scale",
|
||||
"vello_cpu",
|
||||
"vello_cpu 0.0.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hayro"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4675ff5acd7ca41c0c34ccd2a3a154f5c86d8b5ec92bef0a114bfb194969e2af"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"fearless_simd 1.1.0",
|
||||
"hayro-interpret 0.8.0",
|
||||
"image",
|
||||
"kurbo",
|
||||
"pic-scale",
|
||||
"rustc-hash",
|
||||
"vello_cpu 0.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1041,6 +1127,7 @@ version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d285dc30731c8485de5fa732fbdf2b3affdf01e4da7c2135022ca6fa664bf6"
|
||||
dependencies = [
|
||||
"brotli",
|
||||
"hayro-postscript",
|
||||
]
|
||||
|
||||
@@ -1052,13 +1139,32 @@ checksum = "f2613d0406898995042d0794c4245b2f2fba1246490c8ac593769bba6551129d"
|
||||
dependencies = [
|
||||
"bitflags 2.13.2",
|
||||
"hayro-cmap",
|
||||
"hayro-syntax",
|
||||
"hayro-syntax 0.7.2",
|
||||
"kurbo",
|
||||
"moxcms",
|
||||
"phf",
|
||||
"rustc-hash",
|
||||
"siphasher",
|
||||
"skrifa",
|
||||
"skrifa 0.42.1",
|
||||
"smallvec",
|
||||
"yoke",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hayro-interpret"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac9df074ff163a63864cec9b0bf640ccbff8abf4e44481df7369ce0ac172ffbe"
|
||||
dependencies = [
|
||||
"bitflags 2.13.2",
|
||||
"hayro-cmap",
|
||||
"hayro-syntax 0.8.0",
|
||||
"kurbo",
|
||||
"moxcms",
|
||||
"phf",
|
||||
"rustc-hash",
|
||||
"siphasher",
|
||||
"skrifa 0.46.2",
|
||||
"smallvec",
|
||||
"yoke",
|
||||
]
|
||||
@@ -1082,6 +1188,15 @@ dependencies = [
|
||||
"fearless_simd 0.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hayro-jpeg2000"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "122c5f834c37a2260b9c851bb8be685cf539b2a8b94b704a931ef7d2525d5835"
|
||||
dependencies = [
|
||||
"fearless_simd 1.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hayro-postscript"
|
||||
version = "0.1.0"
|
||||
@@ -1095,7 +1210,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7434c89e920d84e077214a29e69b462a6518754610f732f1124af3948410cb8c"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"hayro-interpret",
|
||||
"hayro-interpret 0.7.0",
|
||||
"image",
|
||||
"kurbo",
|
||||
"siphasher",
|
||||
@@ -1111,7 +1226,23 @@ dependencies = [
|
||||
"flate2",
|
||||
"hayro-ccitt 0.3.0",
|
||||
"hayro-jbig2",
|
||||
"hayro-jpeg2000",
|
||||
"hayro-jpeg2000 0.3.5",
|
||||
"memchr",
|
||||
"rustc-hash",
|
||||
"smallvec",
|
||||
"zune-jpeg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hayro-syntax"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6cdc818d8d265dcb42081d488f7599df4f73fb79e9d347ecedcd3c23809d2026"
|
||||
dependencies = [
|
||||
"flate2",
|
||||
"hayro-ccitt 0.4.0",
|
||||
"hayro-jbig2",
|
||||
"hayro-jpeg2000 0.4.1",
|
||||
"memchr",
|
||||
"rustc-hash",
|
||||
"smallvec",
|
||||
@@ -1125,7 +1256,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0b3db92c4917aad24ff30d61413a9a7509ae88b27aee1ae34eff881e1d2723a"
|
||||
dependencies = [
|
||||
"flate2",
|
||||
"hayro-syntax",
|
||||
"hayro-syntax 0.7.2",
|
||||
"pdf-writer",
|
||||
]
|
||||
|
||||
@@ -1553,7 +1684,7 @@ dependencies = [
|
||||
"rustc-hash",
|
||||
"rustybuzz",
|
||||
"siphasher",
|
||||
"skrifa",
|
||||
"skrifa 0.42.1",
|
||||
"smallvec",
|
||||
"subsetter",
|
||||
"tiny-skia-path",
|
||||
@@ -1572,7 +1703,7 @@ dependencies = [
|
||||
"fontdb",
|
||||
"krilla",
|
||||
"resvg",
|
||||
"skrifa",
|
||||
"skrifa 0.42.1",
|
||||
"smallvec",
|
||||
"tiny-skia",
|
||||
"usvg",
|
||||
@@ -1638,6 +1769,7 @@ dependencies = [
|
||||
"csv",
|
||||
"deunicode",
|
||||
"ledger-core",
|
||||
"ledger-reader",
|
||||
"qrcode",
|
||||
"rust_decimal",
|
||||
"rust_xlsxwriter",
|
||||
@@ -1650,6 +1782,18 @@ dependencies = [
|
||||
"typst-pdf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ledger-reader"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"hayro 0.8.0",
|
||||
"hayro-interpret 0.8.0",
|
||||
"kurbo",
|
||||
"quick-xml 0.38.4",
|
||||
"thiserror",
|
||||
"zip 9.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ledger-store"
|
||||
version = "0.1.0"
|
||||
@@ -1659,6 +1803,7 @@ dependencies = [
|
||||
"getrandom 0.2.17",
|
||||
"hex",
|
||||
"ledger-core",
|
||||
"ledger-reader",
|
||||
"libc",
|
||||
"rusqlite",
|
||||
"rust_decimal",
|
||||
@@ -1808,6 +1953,18 @@ version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13d2233c9842d08cfe13f9eac96e207ca6a2ea10b80259ebe8ad0268be27d2af"
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.31.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d"
|
||||
dependencies = [
|
||||
"bitflags 2.13.2",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.8"
|
||||
@@ -2312,7 +2469,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4ed38b89c2c77ff968c524145ad65fb010f38af5c7a224b53b81d47ac2daa81"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"font-types",
|
||||
"font-types 0.11.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "read-fonts"
|
||||
version = "0.41.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "046a7d674daf459825b32f5062056d6882db0d2f5a479fbd76ccfc870ac18709"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"font-types 0.12.7",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "read-fonts"
|
||||
version = "0.43.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "005c8acf251756c478b0bf402885bfd88a1476020c4c7e6060edc1aa68da38ea"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"font-types 0.12.7",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2447,7 +2626,7 @@ version = "0.90.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2be778223b36bb449b2ef2df4856ced2d311680818a7310db5c5dc370170f935"
|
||||
dependencies = [
|
||||
"zip",
|
||||
"zip 4.6.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2637,7 +2816,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c34617370ae968efb7161bb2beb517d9084659aae19e24b89e3db25b46e4564"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"read-fonts",
|
||||
"read-fonts 0.39.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "skrifa"
|
||||
version = "0.44.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "819ab7d62b1d3e72d9d9dea5650bac30424f9111364bb94928dbf5ecad1baa68"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"read-fonts 0.41.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "skrifa"
|
||||
version = "0.46.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4febebda507fb889c545a37a135517769d1391941013561292897961d1887d6"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"read-fonts 0.43.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2724,7 +2923,7 @@ checksum = "38803281d1c23166c5ebcb455439a5d2afe711cc909cf88af72448c297756ad6"
|
||||
dependencies = [
|
||||
"kurbo",
|
||||
"rustc-hash",
|
||||
"skrifa",
|
||||
"skrifa 0.42.1",
|
||||
"write-fonts",
|
||||
]
|
||||
|
||||
@@ -3015,6 +3214,12 @@ version = "2.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a"
|
||||
|
||||
[[package]]
|
||||
name = "typed-path"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ce898823d8cd0f028662d2f349694b1af0a5cc9be83f1d213a00d3147445e1e"
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.20.1"
|
||||
@@ -3164,7 +3369,7 @@ dependencies = [
|
||||
"fontdb",
|
||||
"glidesort",
|
||||
"hayagriva",
|
||||
"hayro-syntax",
|
||||
"hayro-syntax 0.7.2",
|
||||
"icu_properties",
|
||||
"image",
|
||||
"indexmap",
|
||||
@@ -3281,7 +3486,7 @@ dependencies = [
|
||||
"comemo",
|
||||
"ecow",
|
||||
"flate2",
|
||||
"hayro",
|
||||
"hayro 0.7.1",
|
||||
"hayro-svg",
|
||||
"image",
|
||||
"indexmap",
|
||||
@@ -3558,6 +3763,22 @@ dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vello_common"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73c2fbe53548bcd25c8ff42f75a93770a8611a16b37bee56d7ef7b44e36027f1"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"fearless_simd 0.7.0",
|
||||
"guillotiere",
|
||||
"log",
|
||||
"peniko",
|
||||
"png",
|
||||
"smallvec",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vello_cpu"
|
||||
version = "0.0.8"
|
||||
@@ -3565,12 +3786,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d8ded630e8316bb94a55881256506d1f3b9947b5f66db8a7d32ca7ba02decd0"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"glifo",
|
||||
"glifo 0.1.1",
|
||||
"hashbrown 0.17.1",
|
||||
"png",
|
||||
"vello_common 0.0.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vello_cpu"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed1fec424fbba6acf6cbc78bb526447eb77590d95f40419d598870fe37535212"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"glifo 0.4.0",
|
||||
"hashbrown 0.17.1",
|
||||
"png",
|
||||
"vello_common 0.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.5"
|
||||
@@ -3807,11 +4041,11 @@ version = "0.48.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb731d4c4d93eacc69a1ad2f270f905788a98e4a3438267bcafbe08d3431c8d8"
|
||||
dependencies = [
|
||||
"font-types",
|
||||
"font-types 0.11.3",
|
||||
"indexmap",
|
||||
"kurbo",
|
||||
"log",
|
||||
"read-fonts",
|
||||
"read-fonts 0.39.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3962,6 +4196,23 @@ dependencies = [
|
||||
"zopfli",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zip"
|
||||
version = "9.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1156b39d142a34b999c2310a50455e0cb3760bf7efad0122f796d813bee26ccb"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"flate2",
|
||||
"getrandom 0.4.3",
|
||||
"indexmap",
|
||||
"memchr",
|
||||
"nix",
|
||||
"typed-path",
|
||||
"windows-sys",
|
||||
"zopfli",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zlib-rs"
|
||||
version = "0.6.8"
|
||||
|
||||
+1
-1
@@ -1299,7 +1299,7 @@ Each unit follows the 8.0.4 template. "A-n" is an owner answer numbered in 8.3.1
|
||||
5. **Files:** owns `crates/ledger-reader/`; touches `crates/ledger-import/{Cargo.toml,src/lib.rs}`, `crates/ledger-store/Cargo.toml`, `crates/ledger-store/src/store.rs` (imports only), `Cargo.toml` (workspace members), the two fuzz targets' manifest, `docs/architecture.md`, `docs/testing.md`.
|
||||
6. **Tests and proofs:** no new test: the move is behavior-preserving, and P6's `extraction_deterministic`, `xlsx_cells_are_decimal_strings`, `a_pdf_that_crashes_the_reader_is_failed_not_fatal` move with the module and pass unchanged; `fuzz_extract_pdf` and `fuzz_extract_xlsx` build. No kernel, Kani or Lean change.
|
||||
7. **Done when:** (1) `cargo tree -p ledger-store -e normal` shows no `typst*` and no `ledger-import`; (2) `cargo tree -p ledger-import -e normal` shows no `ledger-store` (as today); (3) the three P6 extraction tests and the two fuzz targets pass where they now live; (4) `docs/architecture.md` has no "under review" sentence; (5) the batch's gate (D-60) green.
|
||||
8. **As built:** none yet.
|
||||
8. **As built:** `extract.rs` moved whole (`git mv`) to `crates/ledger-reader/src/lib.rs`; the new crate depends on `thiserror`, `hayro`, `hayro-interpret`, `kurbo`, `zip`, `quick-xml` only. `ledger-import` drops those (keeps `zip` as a dev-dependency for its test) and re-exports the crate with `pub use ledger_reader as extract;`, so `ledger_import::extract::*` still works for `ledger-gui`, `ledger-mcp`, `ledger-host` and the two fuzz targets (no caller changed). `ledger-store` depends on `ledger-reader` instead of `ledger-import`; `store.rs` and `tests/attachments.rs` use `ledger_reader::`. The three P6 tests stay in `crates/ledger-import/tests/extract.rs` (they build their PDFs with `ledger-import`'s statement writer; moving them would need a dev-dependency cycle) and pass through the re-export; the two unit tests moved with the module. `docs/architecture.md`, `docs/testing.md`, `AGENTS.md` updated.
|
||||
|
||||
#### P4b S4: `documents_v2`
|
||||
|
||||
|
||||
Reference in new issue
Block a user