Expand description
Read, validate, repair and write AGS4 — the geotechnical data transfer format.
use laterite::ags4;
// Read
let mut doc = ags4::read("delivery.ags").run()?;
for group in doc.groups() {
println!("{} — {} rows", group.code(), group.len());
}
// Validate — from a path...
let report = ags4::validate("delivery.ags").warnings(true).run()?;
for finding in report.findings() {
println!("{}: {}", finding.rule(), finding.description());
}
// ...or from bytes that never touch a filesystem, for a service that
// validates an upload without giving it a disk to sit on.
let upload: &[u8] = b"\"GROUP\",\"PROJ\"\r\n";
let report = ags4::validate_bytes(upload).run()?;
// Modify and write
doc.set_cell("PROJ", 0, "PROJ_NAME", "Renamed site")?;
ags4::write(&doc).to_path("out.ags")?;
// Repair a delivery mechanically — the result carries what could NOT be
// fixed, and the source file is untouched until you name a destination.
let fixed = ags4::fix("delivery.ags").run()?;
println!("{} repaired, {} left", fixed.fixes_applied(), fixed.findings().len());
// Or construct AGS4 from data you hold rather than a file you read.
use laterite::ags4::GroupData;
let proj = GroupData::new("PROJ", ["PROJ_ID", "PROJ_NAME"]).row(["P1", "A site"]);
let built = ags4::build(vec![proj]).run()?;§What this crate promises
It is a facade. The work happens in a tier of laterite-ags4-* engine
crates, which move on their own version and reshape as the format work
demands. This crate exists so that their reshaping does not reach you —
a promise about the engine, kept by the rules below.
Concretely, and these are the rules the API is built to:
- Everything AGS4-specific lives under
ags4. The crate root stays format-neutral. AGS4 is not the last version of the format, and a root-levellaterite::readwould have to mean one of them forever.transportis at the root because it genuinely is format-neutral — zstd and age over any bytes. - Handles are opaque.
ags4::Document,ags4::Reportand the rest have private fields. You reach data through methods, so the engine’s own structs can change shape without editing your code. - No third-party type appears in a public signature. Not
serde_json::Value, notchrono, notencoding_rs, notarrow. Encodings are WHATWG label strings, dates are ISO strings. This is the highest-leverage rule here: no dependency’s major version can ever force one of ours. - One
Errorwith a coarse,#[non_exhaustive]ErrorKindand a stableError::kind_strshared with the Python, Node andlatsurfaces.
The crate is at parity with the Python and Node surfaces — per
capability, at least what the weaker of those two offers — and carries the
product version: cargo add laterite and pip install laterite name
the same release. While the product line is pre-1.0 a breaking change takes
the minor, and Cargo will not carry you across a 0.x minor on the caret
requirement cargo add writes, so an upgrade is yours to take rather than
something that happens to you.
What that means for every surface is stated once, at https://docs.laterite.dev/reference/support/.
The unstable-engine feature is the only way past the facade. It is a
feature rather than a hidden module because it shows up in your
Cargo.toml — reaching past a stability boundary should be something you
wrote down.
§Scope
Read, validate, fix, build, write, certify, diff, merge, transport
(compress / encrypt any file), and — behind the optional excel feature —
XLSX conversion in both directions.
Parity was reached once, then the crate left 0.1.x for the product line
in a single jump — there was never a 0.2, deliberately: a waypoint version
would have existed for as long as the remaining work took, on a crate whose
purpose is to be a stable surface over a moving engine.
Modules§
- ags4
- The AGS4 surface: read, validate, fix, build, write, diff, merge — and,
behind the
excelfeature, XLSX conversion in both directions. - transport
- Compress and encrypt any file — zstd, and zstd + an age passphrase.
Structs§
- Error
- An error from any laterite operation.
Enums§
- Error
Kind - What went wrong, coarsely.