rd-rds 0.3.0

Read-only reader for the subset of R's RDS serialization format used by installed-package help databases
Documentation

rd-rds

rd-rds is a scoped, read-only reader for installed-R-package information and selected CRAN-like repository indexes. It is not a general R serialization library and never silently accepts an unknown SEXP. See the workspace README for repository status and crate relationships.

The API has three layers:

  • parse reads a decompressed XDR serialization stream only.
  • file::from_bytes and file::read accept the complete envelope and apply bounded decompression. Supported envelopes are raw X\n XDR, gzip, xz, bzip2, and zstd (when the corresponding feature is enabled).
  • package provides validated convenience views for Meta/package.rds and CRAN-like PACKAGES.rds matrices.
  • matrix::CharacterMatrix provides a validated, owned view of general R character matrices, including matrices without dimnames.

The rd-helpdb crate uses the file layer for standalone help-database RDS files, and rd-ast can lower supported decoded documentation objects into the common document model.

Runnable examples

cargo run -p rd-rds --example inspect_packages -- /path/to/PACKAGES.rds
cargo run -p rd-rds --example inspect_rds -- /path/to/archive.rds

inspect_packages demonstrates the typed, stable package-index view. inspect_rds provides a bounded advanced inspection of unfamiliar decoded objects, including shapes that are not package matrices.

Repository-index interoperability

The supported contract is the tested decoding behaviour described in the workspace stability policy, not the continued availability or unchanged schema of files hosted by third parties. Deterministic fixtures cover these CRAN profiles:

  • src/contrib/PACKAGES.rds: xz envelope, serialization format 2, and the 17-column main-index schema.
  • src/contrib/Archive/<package>/PACKAGES.rds: gzip envelope, serialization format 3, and the 15-column package-archive schema.
  • src/contrib/Meta/archive.rds: gzip envelope, serialization format 3, and a named list of file.info()-shaped data frames.

Real CRAN examples were compared cell-for-cell with R 4.6.1 readRDS() on 2026-08-04; decoded cell values matched in all three profiles. R-universe was manually verified on 2026-08-05: source indexes used gzip, the Windows and macOS binary-repository indexes used zstd, and the observed schema had 15 columns with SHA256 in place of CRAN's MD5sum. These observations fall within the reader's general matrix, encoding, and compression behaviour, but the test suite contains no R-universe-specific fixture.

These statements describe observed interoperability at the stated dates. They do not guarantee that an external service retains the same paths, schemas, compression, or serialization behaviour.

Upstream archive semantics

These are upstream semantics, not reader guarantees. As observed on 2026-08-04, CRAN's per-package Archive/<package>/PACKAGES.rds excludes the current package version, and its rows are in archival rather than semantic-version order. Consumers must not infer inclusion of the current release or version precedence from row position. This is a recently introduced and undocumented CRAN facility and may change or disappear independently of rd-rds.

String encoding metadata

RStr::encoding() reports the CHARSXP encoding flag stored in the serialized data. R-universe files are generated by a JavaScript serializer rather than by R, and currently flag every string as UTF-8, including ASCII-only strings, while R's Encoding() reports those strings as "unknown" after readRDS(). Encoding labels can therefore differ even when decoded string contents are identical; this is not a decoding incompatibility.

Unknown or unsupported SEXP values reachable from the decoded result are hard decode errors; they are never silently converted to a known value. The one exception is environment internals: environments are collapsed to opaque handles, and a limited set of verified value shapes inside them (for example complex, raw, and S4 objects) is wire-consumed and discarded rather than rejected. Decoder defaults are a depth limit of 5,000, a vector limit of 8,000,000 elements, and a total-element limit of 16,000,000. The file layer defaults to 256 MiB compressed and decompressed input caps.

RObject and RValue access is a supported advanced API. Their fields are encapsulated and accessed through constructors and accessors. Enum variants may be added in minor releases, so consumers must use wildcard match arms; the public enums are non-exhaustive. The typed package and matrix views are the stable convenience surface for ordinary consumers.

Stability

Typed package-metadata views are the recommended supported surface. The RObject/RValue object model is supported as an advanced surface, with variants subject to addition; unsupported SEXPs are hard errors except for selected environment internals consumed as opaque or discarded wire data. See the workspace stability policy.

License

MIT; see the workspace license.