Add R language SDK#177
Conversation
|
Companion website documentation PR: json-structure/site#5 |
|
Note: the |
C workflow
|
Add an official R SDK (r/) mirroring the Ruby SDK architecture: a thin compiled shim (src/shim.c) loads the prebuilt json_structure C library at runtime (downloaded from GitHub Releases on first use, or via JSONSTRUCTURE_LIB_PATH) and exposes idiomatic R validation functions. - src/shim.c + init.c: dlopen / LoadLibraryExW dynamic loading, ABI re-declared to match c/include headers, columnar .Call result marshaling - R/: public API (js_validate_schema[_strict], js_validate_instance[_strict], is_valid, message and data.frame accessors), lazy library loading, binary downloader/cache, and a faithful port of Ruby's extension-keyword checks - tests/testthat: pure-R, binding, and shared-corpus conformance tests that skip gracefully when the native library or assets are absent - man/: documentation for all exported functions - .github/workflows/r.yml: multi-OS R CMD check + conformance + release - README.md, SDK-GUIDELINES.md: document the new SDK The C release workflow change needed to publish the prebuilt libraries the R (and Ruby) downloaders consume is handled separately in #178. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Reorg: this PR no longer touches c.yml. The Windows CMake configure fix and the release-asset attachment now live in #178, so this is a pure R-package PR. It no longer triggers the C SDK workflow; the R SDK workflow covers it end-to-end. |
Addresses the findings from an R-community best-practices review of the
R SDK. No changes to the shared C library (c/), so the C workflow is not
triggered.
Loading & consent
- Never download the native library implicitly. .onLoad no longer loads the
engine eagerly; loading is deferred to first use and resolves only an
env-override (JSONSTRUCTURE_LIB_PATH) or the local cache. When absent, the
user is asked for consent (interactive) or given an actionable error
(non-interactive/CRAN/CI) instead of a silent network fetch.
- install_jsonstructure_binary() remains the explicit, user-invoked download.
Download integrity
- Verify a SHA-256 checksum before extracting a downloaded archive. The
expected digest resolves from sha256=, JSONSTRUCTURE_BINARY_SHA256, or a
shipped inst/checksums.dcf manifest; mismatch aborts, and when no digest is
available the computed one is reported so it can be pinned.
- Checksums are computed via tools::sha256sum with openssl/digest fallbacks
(added to Suggests). Hash comparison is attribute-safe across backends.
- Extraction prefers the exact expected library name so archive contents
cannot silently substitute a differently named library.
Native shim
- Load the engine with reduced symbol scope: RTLD_LOCAL on Unix and
LOAD_LIBRARY_SEARCH_* (with a safe fallback) on Windows.
- Guarantee js_result_cleanup() via R_UnwindProtect when marshalling results,
so a failed R allocation cannot leak native memory.
- Add an optional ABI-major version probe and a binding_version() routine.
Error handling & docs
- Replace stopifnot() in the result accessors with explicit stop(call.=FALSE).
- Regenerate NAMESPACE/man with roxygen2 (markdown); export the previously
missing js_warning_messages plus new jsonstructure_binary_version.
- Convert \dontrun{} examples that need the engine to @examplesIf guards so
they run when the binding is available and are skipped otherwise.
Testing & tooling
- skip_if_no_binding() is network-free and skip_on_cran(): it only uses an
already-resolved library and never downloads.
- Add .lintr config; document the lintr CI step as advisory.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Document the new R language SDK alongside the other SDKs: - sdks/r.md: dedicated R SDK page (install via remotes::install_github with subdir = 'r', not on CRAN, usage snippet, JSONSTRUCTURE_LIB_PATH note) - _layouts/sdk-index.html: add R to the sidebar nav and an R SDK card - index.md: add an R row to the SDKs table Companion to json-structure/sdk#177. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Summary
Adds an official R language SDK (
r/) alongside the existing SDKs. It mirrors the Ruby SDK's architecture: because interpreted recursive validation is slow, the R package reuses the proven C validation engine through a thin compiled.Callshim rather than reimplementing the validator in R.The shim
dlopens a prebuiltjson_structureshared library downloaded from GitHub Releases on first use (or pointed at byJSONSTRUCTURE_LIB_PATH). Nothing is vendored, and the package is intentionally not on CRAN (CRAN forbids downloading binaries at runtime).What's included
r/src/shim.c,r/src/init.c— dynamic loading (dlopen/dlsymon Unix,LoadLibraryExWon Windows), the C ABI re-declared to matchc/include/json_structure/*.hexactly, and columnar.Callresult marshaling. Registers 5 routines withR_useDynamicSymbols(FALSE)/R_forceSymbols(TRUE).r/R/— idiomatic public API:js_validate_schema[_strict](),js_validate_instance[_strict](),is_valid(),js_error_messages()/js_warning_messages(),as.data.frame(), plus lazy library loading, the binary downloader/cache, and a faithful port of Ruby's R-side extension-keyword checks (units, relations,$usesgating, identifiers, tuple$ref, enum typing) — defensivelytryCatch-wrapped so it can never turn a passing base result into a failure.r/tests/testthat/— pure-R tests (run without the binary), binding tests, and shared-corpus conformance tests (mirroring Ruby'stest_assets_spec.rb) that skip gracefully when the native library ortest-assets/are unavailable.r/man/— documentation for every exported function..github/workflows/r.yml— new CI:R CMD check+ conformance across ubuntu/macos (R release + oldrel-1), a Windows shim-compile job, a lint job, and a release-on-tag job that uploads the R source tarball.Shared prerequisite: C release assets
js_validate_*downloads the prebuilt library fromreleases/download/vX.Y.Z/json_structure-<os>-<arch>.tar.gz. The C release job previously published only versioned workflow artifacts, so this URL would 404 for both Ruby and R. This PR makes an additive fix to.github/workflows/c.ymlto also attach installer-named archives (json_structure-linux-x86_64,json_structure-macos-arm64,json_structure-windows-x86_64) to the GitHub Release. No existing behavior is removed.Validation note
There is no R runtime or C compiler in the authoring environment, so the package was validated by rigorous static review plus an independent code review:
{ options }, so the stack allocations cannot overflow.NAMESPACEexport and S3 method has a matching definition andman/alias.LoadLibraryExW;-ldlis linked only on Linux/Solaris (via a GNU-make conditional, declared inSystemRequirements) so macOS builds cleanly; and the augmentation keyword sets were aligned exactly to the Ruby constants.End-to-end compile/run is exercised by the new CI.
Website
Documentation for the project website is in the companion PR in
json-structure/site.Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com