Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v6
- name: Setup Pixi
uses: prefix-dev/setup-pixi@v0.9.4
uses: prefix-dev/setup-pixi@v0.10.0
with:
pixi-version: v0.65.0
cache: true
pixi-version: v0.72.0
environments: dev
cache: true
cache-write: ${{ github.event_name == 'push' && github.ref_name == 'main' }}
- name: Run checks and formatters through pre-commit
run: pixi run pre-commit run --all-files

Expand All @@ -36,11 +37,12 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v6
- name: Setup Pixi
uses: prefix-dev/setup-pixi@v0.9.5
uses: prefix-dev/setup-pixi@v0.10.0
with:
pixi-version: v0.66.0
cache: true
pixi-version: v0.72.0
environments: dev
cache: true
cache-write: ${{ github.event_name == 'push' && github.ref_name == 'main' }}
- name: Set Windows link flags for R
if: runner.os == 'Windows'
shell: pwsh
Expand Down
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ repos:
args: ['--fix=lf']
- id: check-yaml
- id: check-json
- id: check-toml
- id: check-merge-conflict
- id: check-added-large-files
- repo: https://github.com/python-jsonschema/check-jsonschema
Expand All @@ -23,9 +22,10 @@ repos:
# Formatters
- id: pixi-format-cargo
name: "Run cargo format through pixi"
entry: pixi run fmt-cargo --
entry: pixi run fmt-cargo
language: system
types_or: [rust]
pass_filenames: false
- id: pixi-format-air
name: "Run air format through pixi"
entry: pixi run fmt-air
Expand Down
3 changes: 2 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ Description: Provides R bindings to y-crdt, a Rust implementation of the
License: MIT + file LICENSE
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.3.3
Config/rextendr/version: 0.4.2.9000
SystemRequirements: Cargo (Rust's package manager), rustc >= 1.65.0, xz
Depends:
Expand All @@ -25,3 +24,5 @@ Collate:
'text.R'
'transaction.R'
'update.R'
'zzz.R'
Config/roxygen2/version: 8.0.0
3 changes: 0 additions & 3 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,6 @@ S3method("[[",Transaction)
S3method("[[",TransactionCleanupEvent)
S3method("[[",Unsupported)
S3method("[[",Update)
S3method(print,Doc)
S3method(print,Origin)
S3method(print,Update)
export(ArrayRef)
export(DeleteSet)
export(Doc)
Expand Down
6 changes: 0 additions & 6 deletions R/doc.R
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,6 @@ NULL
#' @export
`[[.TransactionCleanupEvent` <- `$.TransactionCleanupEvent`

#' @export
print.Doc <- function(self, ...) {
cat(self$to_string(), "\n", sep = "")
invisible(self)
}

Doc$with_transaction <- function(callback, mutable = FALSE, origin = NULL) {
transaction <- Transaction$lock(self, mutable = mutable, origin = origin)
on.exit(transaction$unlock())
Expand Down
4 changes: 2 additions & 2 deletions R/error-wrapper.R
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ throw_if_condition <- function(res) {
#' Returns a replacement for the generated `$.<Class>` S3 method. The
#' dispatcher looks up `name` in `env`; if it is missing but `<name>_ec`
#' exists, the fallible binding is invoked and its result passed through
#' [throw_if_condition()]. The wrapper is rebuilt on every call because
#' `throw_if_condition()`. The wrapper is rebuilt on every call because
#' the generated dispatcher injects `self` by rewriting the function's
#' closure environment, which would clobber any captured state set up
#' once at install time.
Expand Down Expand Up @@ -63,7 +63,7 @@ make_dispatcher <- function(env) {
#' (e.g. `Origin$new(...)`), bypassing the `$.<Class>` S3 dispatcher,
#' so they need their own bare-name alias. This installs `env[[name]]`
#' as a wrapper that forwards to `env[[paste0(name, "_ec")]]` and runs
#' the result through [throw_if_condition()].
#' the result through `throw_if_condition()`.
#'
#' @param env Environment holding the class's generated bindings.
#' @param name Bare (un-suffixed) name to expose. The fallible binding
Expand Down
6 changes: 6 additions & 0 deletions R/extendr-wrappers.R
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ Origin$greater_than_equal <- function(other) .Call(wrap__Origin__greater_than_eq

Origin$to_string <- function() .Call(wrap__Origin__to_string, self)

Origin$`__yr_print__` <- function() .Call(wrap__Origin____yr_print__, self)

Origin$to_bytes <- function() .Call(wrap__Origin__to_bytes, self)

Origin$to_hex <- function() .Call(wrap__Origin__to_hex, self)
Expand Down Expand Up @@ -409,6 +411,8 @@ Update$state_vector_lower <- function() .Call(wrap__Update__state_vector_lower,

Update$to_string <- function() .Call(wrap__Update__to_string, self)

Update$`__yr_print__` <- function() .Call(wrap__Update____yr_print__, self)

#' @export
`$.Update` <- function (self, name) { func <- Update[[name]]; environment(func) <- environment(); func }

Expand All @@ -431,6 +435,8 @@ Doc$get_or_insert_array <- function(name) .Call(wrap__Doc__get_or_insert_array,

Doc$to_string <- function() .Call(wrap__Doc__to_string, self)

Doc$`__yr_print__` <- function() .Call(wrap__Doc____yr_print__, self)

Doc$observe_transaction_cleanup_ec <- function(f, key) .Call(wrap__Doc__observe_transaction_cleanup_ec, self, f, key)

Doc$unobserve_transaction_cleanup_ec <- function(key) .Call(wrap__Doc__unobserve_transaction_cleanup_ec, self, key)
Expand Down
6 changes: 0 additions & 6 deletions R/transaction.R
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,6 @@ NULL

install_checked_static(Origin, "new")

#' @export
print.Origin <- function(self, ...) {
cat(self$to_string(), "\n", sep = "")
invisible(self)
}

#' @export
`==.Origin` <- function(e1, e2) {
e1$equal(e2)
Expand Down
6 changes: 0 additions & 6 deletions R/update.R
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,3 @@ NULL

install_checked_static(Update, "decode_v1")
install_checked_static(Update, "decode_v2")

#' @export
print.Update <- function(x, ...) {
cat(x$to_string(), "\n", sep = "")
invisible(x)
}
35 changes: 35 additions & 0 deletions R/zzz.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#' @include extendr-wrappers.R
NULL

# Rust-side convention: any `#[extendr]` method named `PRINT_METHOD` returns the
# object's textual representation (akin to Python's `__repr__`). Such a method is
# registered automatically as the S3 `print` method for its class in `.onLoad()`,
# so Rust owns the formatting and no per-class R code is required.
PRINT_METHOD <- "__yr_print__"

# Shared S3 `format`/`print` methods: format returns the Rust-owned string,
# print emits it. `[[` binds `self` before calling the `PRINT_METHOD` binding.
format_yr <- function(x, ...) {
x[[PRINT_METHOD]]()
}

print_yr <- function(x, ...) {
cat(format(x, ...), "\n", sep = "")
invisible(x)
}

# Register `print`/`format` for every extendr class exposing a `PRINT_METHOD`
# binding, so a `__yr_print__` method on the Rust side is all that's needed.
.onLoad <- function(libname, pkgname) {
ns <- asNamespace(pkgname)
for (name in ls(ns, all.names = TRUE)) {
obj <- get0(name, envir = ns, inherits = FALSE)
if (
is.environment(obj) &&
exists(PRINT_METHOD, envir = obj, inherits = FALSE)
) {
registerS3method("print", name, print_yr, envir = ns)
registerS3method("format", name, format_yr, envir = ns)
}
}
}
Loading