gedcomkit 0.1.14__tar.gz → 0.1.16__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/CHANGELOG.md +66 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/Cargo.lock +1 -1
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/Cargo.toml +1 -1
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/PKG-INFO +1 -1
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/bindings/gedcomkit-py/Cargo.lock +2 -2
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/bindings/gedcomkit-py/Cargo.toml +1 -1
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/bindings/gedcomkit-py/src/lib.rs +30 -7
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/src/gedzip.rs +1557 -119
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/src/lib.rs +240 -1
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/LICENSE +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/README.md +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/bindings/gedcomkit-py/LICENSE +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/bindings/gedcomkit-py/README.md +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/bindings/gedcomkit-py/gedcomkit.pyi +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom-spec/LICENSE +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom-spec/README.md +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom-spec/cardinalities.tsv +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom-spec/enumerations.tsv +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom-spec/enumerationsets.tsv +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom-spec/grammar.abnf +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom-spec/grammar.gedstruct +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom-spec/payloads.tsv +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom-spec/substructures.tsv +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/5/age-invalid.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/5/age-valid.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/5/atsign.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/5/char_ascii_1.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/5/char_ascii_2.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/5/char_utf16be-1.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/5/char_utf16be-2.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/5/char_utf16le-1.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/5/char_utf16le-2.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/5/char_utf8-1.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/5/char_utf8-2.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/5/char_utf8-3.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/5/date-all.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/5/date-dual-invalid.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/5/date-dual-valid.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/5/enum-ext.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/5/filename-1.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/5/lang-all.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/5/notes-1.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/5/obje-1.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/5/obsolete-1.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/5/pedi-1.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/5/rela_1.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/5/sour-1.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/5/tiny-1.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/5/xref-case.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/7/age-invalid.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/7/age-valid.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/7/atsign.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/7/char_ascii_1.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/7/char_ascii_2.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/7/char_utf16be-1.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/7/char_utf16be-2.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/7/char_utf16le-1.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/7/char_utf16le-2.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/7/char_utf8-1.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/7/char_utf8-2.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/7/char_utf8-3.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/7/date-all.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/7/date-dual-invalid.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/7/enum-ext.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/7/filename-1.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/7/lang-all.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/7/notes-1.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/7/obje-1.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/7/obsolete-1.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/7/pedi-1.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/7/rela_1.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/7/sour-1.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/7/tiny-1.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/7/xref-case.ged +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/LICENSE +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/gedcom7code/UPSTREAM-README.md +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/zip-interop/README.md +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/zip-interop/python-zip64.gdz +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/fixtures/vendored/zip-interop/python-zipfile.gdz +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/pyproject.toml +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/src/build.rs +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/src/convert.rs +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/src/dates.rs +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/src/decode.rs +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/src/family.rs +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/src/names.rs +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/src/schema.rs +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/src/synthetic.rs +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/src/tags.rs +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/src/validate.rs +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/src/view.rs +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/tests/endurance.rs +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/tests/external_charset.rs +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/tests/properties.rs +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/tests/requirement_corpus.rs +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/tests/spec_conformance.rs +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/tests/typescript.rs +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/tests/vendored_corpus.rs +0 -0
- {gedcomkit-0.1.14 → gedcomkit-0.1.16}/tests/version_conversion.rs +0 -0
|
@@ -5,6 +5,72 @@ format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
|
|
|
5
5
|
the project uses semantic versioning within the usual pre-1.0 compatibility
|
|
6
6
|
rules.
|
|
7
7
|
|
|
8
|
+
## [0.1.16] - 2026-10-14
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- `Document::record_index` builds a `RecordIndex` that answers
|
|
13
|
+
`get(xref)`, `position(xref)`, and `contains(xref)` in constant time,
|
|
14
|
+
exactly as `Document::record` does: ASCII case folded, other characters
|
|
15
|
+
compared as themselves, the first of two records with one identifier
|
|
16
|
+
winning. It borrows the document, so the compiler refuses any edit to
|
|
17
|
+
`records` while it is alive and no answer can be stale; build one per
|
|
18
|
+
batch of lookups (a page of rows, a chart) instead of calling `record`
|
|
19
|
+
per item, which scans. No identifier is copied to build it.
|
|
20
|
+
- `gedzip::ArchiveWriter::add_streamed(name, source, size)`, for a sink that
|
|
21
|
+
is also `Seek`, writes an entry from any `Read` in 64 KiB chunks, so an
|
|
22
|
+
entry costs one buffer rather than about twice its size. Its size is
|
|
23
|
+
bounded by `ArchiveLimits::entry_bytes` alone (1 GiB by default); a writer
|
|
24
|
+
made with `new_with` and a higher figure takes entries past 4 GiB, through
|
|
25
|
+
Zip64. The local header is written first, with a Zip64 extra when the
|
|
26
|
+
entry needs one; the CRC-32 is computed as the bytes pass, and the writer
|
|
27
|
+
seeks back to fill it in and the compressed size, so the header is as
|
|
28
|
+
complete as `add`'s (no data descriptor). A stored entry is byte-for-byte
|
|
29
|
+
what `add` writes. `size` is checked against `entry_bytes` before anything
|
|
30
|
+
is written; a source that yields more or fewer bytes than `size`, a failing
|
|
31
|
+
source, a failed seek, or a sink that does not overwrite in place after a
|
|
32
|
+
seek (a file opened for appending) poisons the writer, since the sink then
|
|
33
|
+
holds a partial entry. A name `add` would deflate is deflated here too, but
|
|
34
|
+
kept deflated even when that did not make it smaller; and since its Zip64
|
|
35
|
+
need is settled against a bound before the compressed size is known, a
|
|
36
|
+
deflated entry within about an eighth of 4 GiB may carry a Zip64 extra in
|
|
37
|
+
its local header while its directory record is plain, which the format
|
|
38
|
+
allows.
|
|
39
|
+
|
|
40
|
+
### Changed
|
|
41
|
+
|
|
42
|
+
- The Python binding's `ArchiveFileWriter.add_file` now streams the file
|
|
43
|
+
through `add_streamed` instead of reading it into memory, so adding a file
|
|
44
|
+
costs one buffer; the per-entry limit stays the default 1 GiB. It refuses
|
|
45
|
+
anything but a regular file before writing. The binding surfaces are
|
|
46
|
+
unchanged.
|
|
47
|
+
- `Document::xref_index` documents that its owned map can go stale after an
|
|
48
|
+
edit, and points to `record_index`.
|
|
49
|
+
|
|
50
|
+
## [0.1.15] - 2026-10-11
|
|
51
|
+
|
|
52
|
+
### Added
|
|
53
|
+
|
|
54
|
+
- `gedzip::Archive::copy_entry` decompresses one entry into any
|
|
55
|
+
`std::io::Write` in 64 KiB chunks and returns the byte count, so an entry
|
|
56
|
+
of any size can be extracted without holding it in memory. It enforces the
|
|
57
|
+
same rules as `read_entry`: the local header must agree with the directory,
|
|
58
|
+
the entry may not outgrow its declared size, the per-file and ratio limits
|
|
59
|
+
are checked against the bytes as they accumulate, and the CRC-32 is
|
|
60
|
+
verified at the end. The sink may already have received bytes when an error
|
|
61
|
+
is returned, so write to a temporary file and move it into place on success.
|
|
62
|
+
|
|
63
|
+
### Changed
|
|
64
|
+
|
|
65
|
+
- `Archive::read_entry` is now `copy_entry` into a `Vec`, so the two share one
|
|
66
|
+
validation path and cannot disagree. Results and error messages are
|
|
67
|
+
unchanged.
|
|
68
|
+
- The per-file and compression-ratio checks at open and at extraction are one
|
|
69
|
+
function, and `copy_entry` re-applies them to the entry it is handed.
|
|
70
|
+
- `Archive::open_with` follows the Zip64 directory when the end record's
|
|
71
|
+
directory size is the `0xFFFF_FFFF` marker, as the writer promotes on it.
|
|
72
|
+
Before, only the entry count and offset were consulted.
|
|
73
|
+
|
|
8
74
|
## [0.1.14] - 2026-10-10
|
|
9
75
|
|
|
10
76
|
### Fixed
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# was checked on crates.io, npm, and PyPI before the initial release.
|
|
4
4
|
[package]
|
|
5
5
|
name = "gedcomkit"
|
|
6
|
-
version = "0.1.
|
|
6
|
+
version = "0.1.16"
|
|
7
7
|
description = "A byte-preserving GEDCOM document model: decoding, parsing, readings, version conversion, plausibility checks, and the GEDZIP container, for GEDCOM 5.5 through 7.x."
|
|
8
8
|
edition = "2024"
|
|
9
9
|
# The true minimum, not the workspace's toolchain: a parser library is a leaf
|
|
@@ -35,7 +35,7 @@ dependencies = [
|
|
|
35
35
|
|
|
36
36
|
[[package]]
|
|
37
37
|
name = "gedcomkit"
|
|
38
|
-
version = "0.1.
|
|
38
|
+
version = "0.1.16"
|
|
39
39
|
dependencies = [
|
|
40
40
|
"flate2",
|
|
41
41
|
"serde",
|
|
@@ -43,7 +43,7 @@ dependencies = [
|
|
|
43
43
|
|
|
44
44
|
[[package]]
|
|
45
45
|
name = "gedcomkit-py"
|
|
46
|
-
version = "0.1.
|
|
46
|
+
version = "0.1.16"
|
|
47
47
|
dependencies = [
|
|
48
48
|
"gedcomkit",
|
|
49
49
|
"pyo3",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# abi3 keeps it to one wheel per platform across Python versions.
|
|
3
3
|
[package]
|
|
4
4
|
name = "gedcomkit-py"
|
|
5
|
-
version = "0.1.
|
|
5
|
+
version = "0.1.16"
|
|
6
6
|
description = "Python bindings for gedcomkit: an archival-grade GEDCOM library — byte-preserving round-trip, encoding detection, GEDCOM 5.5 through 7.x, GEDZIP."
|
|
7
7
|
edition = "2024"
|
|
8
8
|
rust-version = "1.88"
|
|
@@ -20,7 +20,7 @@ use pyo3::types::{PyBytes, PyModule};
|
|
|
20
20
|
use pyo3::wrap_pyfunction;
|
|
21
21
|
use serde::Serialize;
|
|
22
22
|
use std::fs::File;
|
|
23
|
-
use std::io::{BufWriter, Write as _};
|
|
23
|
+
use std::io::{BufReader, BufWriter, Write as _};
|
|
24
24
|
use std::path::PathBuf;
|
|
25
25
|
|
|
26
26
|
/// A parsed GEDCOM document and the report of how its bytes were read.
|
|
@@ -432,8 +432,11 @@ impl Default for ArchiveWriter {
|
|
|
432
432
|
}
|
|
433
433
|
|
|
434
434
|
/// Writes a GEDZIP archive straight to a file, one entry at a time, so
|
|
435
|
-
/// memory stays a small multiple of the largest
|
|
436
|
-
///
|
|
435
|
+
/// memory stays a small multiple of the largest entry passed as bytes to
|
|
436
|
+
/// `add` — and one 64 KiB buffer for an entry streamed with `add_file` —
|
|
437
|
+
/// however large the archive grows. Each entry may be at most the library's
|
|
438
|
+
/// default per-entry limit, 1 GiB (`ArchiveLimits` has no Python binding
|
|
439
|
+
/// yet). Python only: the WASM binding has no filesystem.
|
|
437
440
|
///
|
|
438
441
|
/// The file is created at once and is complete only after `finish`; an
|
|
439
442
|
/// archive abandoned part-way (an error, or no `finish`) leaves a partial
|
|
@@ -466,12 +469,32 @@ impl ArchiveFileWriter {
|
|
|
466
469
|
self.writer()?.add(name, data).map_err(value_error)
|
|
467
470
|
}
|
|
468
471
|
|
|
469
|
-
/// Adds one entry read from the file at `source`, without the
|
|
470
|
-
/// passing through Python
|
|
471
|
-
///
|
|
472
|
+
/// Adds one entry read from the regular file at `source`, without the
|
|
473
|
+
/// bytes ever passing through Python, and without holding the file in
|
|
474
|
+
/// memory: it streams in 64 KiB chunks, so it costs one buffer. The file
|
|
475
|
+
/// may be at most the writer's per-entry limit, the library's default of
|
|
476
|
+
/// 1 GiB. Raises `OSError` when it cannot be opened, `ValueError` when it
|
|
477
|
+
/// is not a regular file or as `add` does, and `ValueError` when the
|
|
478
|
+
/// file changes size while it is read — after which the archive cannot
|
|
479
|
+
/// be finished.
|
|
472
480
|
fn add_file(&mut self, name: &str, source: PathBuf) -> PyResult<()> {
|
|
473
481
|
let file = File::open(&source).map_err(|error| os_error(&source, &error))?;
|
|
474
|
-
|
|
482
|
+
let metadata = file
|
|
483
|
+
.metadata()
|
|
484
|
+
.map_err(|error| os_error(&source, &error))?;
|
|
485
|
+
// A directory, pipe, or device reports no usable length, and would
|
|
486
|
+
// fail part-way through the entry; refuse it before anything is
|
|
487
|
+
// written, which leaves the archive usable.
|
|
488
|
+
if !metadata.is_file() {
|
|
489
|
+
return Err(PyValueError::new_err(format!(
|
|
490
|
+
"{} is not a regular file",
|
|
491
|
+
source.display()
|
|
492
|
+
)));
|
|
493
|
+
}
|
|
494
|
+
let size = metadata.len();
|
|
495
|
+
self.writer()?
|
|
496
|
+
.add_streamed(name, BufReader::new(file), size)
|
|
497
|
+
.map_err(value_error)
|
|
475
498
|
}
|
|
476
499
|
|
|
477
500
|
/// Writes the central directory, flushes, and closes the file, returning
|