Skip to content

Commit

Permalink
Makes Serial Config an Open Standard (#53)
Browse files Browse the repository at this point in the history
* make serial_config available to R construction; validate when setting option

* advance version

* add tests
  • Loading branch information
shikokuchuo authored Oct 4, 2024
1 parent 2975514 commit c522770
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 8 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: nanonext
Type: Package
Title: NNG (Nanomsg Next Gen) Lightweight Messaging Library
Version: 1.2.1.9025
Version: 1.2.1.9026
Description: R binding for NNG (Nanomsg Next Gen), a successor to ZeroMQ. NNG is
a socket library implementing 'Scalability Protocols', a reliable,
high-performance standard for common communications patterns including
Expand Down
3 changes: 2 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# nanonext 1.2.1.9025 (development)
# nanonext 1.2.1.9026 (development)

#### New Features

Expand All @@ -7,6 +7,7 @@

#### Updates

* `serial_config()` now validates all arguments and returns them as a list. Full validation is also performed when the option is set for additional safety.
* Warning messages for unserialization or conversion failures of received data are now suppressable.
* Upgrades `reply()` to always return even when there is an evaluation error. This allows it to be used safely in a loop without exiting early, for example.
* Removes deprecated and defunct `next_config()`.
Expand Down
2 changes: 1 addition & 1 deletion src/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ static SEXP rawOneString(unsigned char *bytes, R_xlen_t nbytes, R_xlen_t *np) {

static SEXP nano_inHook(SEXP x, SEXP hook) {

if (!Rf_inherits(x, CHAR(CAR(hook))))
if (!Rf_inherits(x, NANO_STRING(CAR(hook))))
return R_NilValue;

SEXP newlist, list, newnames, names, out;
Expand Down
24 changes: 20 additions & 4 deletions src/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,19 @@ SEXP rnng_set_opt(SEXP object, SEXP opt, SEXP value) {
case VECSXP:
if (strncmp(op, "serial", 6))
Rf_error("type of 'value' not supported");
SEXPTYPE typ = TYPEOF(NANO_VECTOR(value)[0]);
if (typ != CHARSXP && typ != NILSXP) {
xc = 3; break;
R_xlen_t xlen = Rf_xlength(value);
if (xlen > 0) {
if (Rf_xlength(value) != 4 ||
TYPEOF(NANO_VECTOR(value)[0]) != STRSXP ||
TYPEOF(NANO_VECTOR(value)[3]) != LGLSXP) {
xc = 3; break;
}
SEXPTYPE typ1 = TYPEOF(NANO_VECTOR(value)[1]);
SEXPTYPE typ2 = TYPEOF(NANO_VECTOR(value)[2]);
if (!(typ1 == CLOSXP || typ1 == SPECIALSXP || typ1 == BUILTINSXP) ||
!(typ2 == CLOSXP || typ2 == SPECIALSXP || typ2 == BUILTINSXP)) {
xc = 3; break;
}
}
NANO_SET_PROT(object, Rf_VectorToPairList(value));
xc = 0;
Expand Down Expand Up @@ -556,7 +566,10 @@ SEXP rnng_serial_config(SEXP klass, SEXP sfunc, SEXP ufunc, SEXP vec) {
SEXP out;
PROTECT(out = Rf_allocVector(VECSXP, 4));

SET_VECTOR_ELT(out, 0, STRING_ELT(klass, 0));
if (TYPEOF(klass) != STRSXP)
Rf_error("'class' must be a character string");

SET_VECTOR_ELT(out, 0, klass);

SEXPTYPE typ1 = TYPEOF(sfunc);
SEXPTYPE typ2 = TYPEOF(ufunc);
Expand All @@ -566,6 +579,9 @@ SEXP rnng_serial_config(SEXP klass, SEXP sfunc, SEXP ufunc, SEXP vec) {
SET_VECTOR_ELT(out, 1, sfunc);
SET_VECTOR_ELT(out, 2, ufunc);

if (TYPEOF(vec) != LGLSXP)
Rf_error("'vec' must be a logical value");

SET_VECTOR_ELT(out, 3, Rf_ScalarLogical(NANO_INTEGER(vec) ? 1 : 0));

UNPROTECT(1);
Expand Down
8 changes: 7 additions & 1 deletion tests/tests.R
Original file line number Diff line number Diff line change
Expand Up @@ -264,17 +264,23 @@ opt(rep, "serial") <- cfg
custom <- list(`class<-`(new.env(), "custom"), new.env())
test_zero(send(req$socket, custom, mode = "serial", block = 500))
test_type("integer", recv(rep, block = 500)[[1L]])
cfg <- serial_config("custom", function(x) as.raw(length(x)), function(x) lapply(seq_len(as.integer(x)), new.env), vec = TRUE)
cfg <- serial_config("custom", function(x) as.raw(length(x)), function(x) lapply(seq_len(as.integer(x)), new.env), vec = NA)
test_true(cfg[[4L]])
opt(req$socket, "serial") <- cfg
opt(rep, "serial") <- cfg
test_zero(send(rep, custom, block = 500))
test_type("list", recv(req$socket, mode = 1L, block = 500))
opt(req$socket, "serial") <- list()
opt(rep, "serial") <- list()
test_error(serial_config(1L, identity, identity), "must be a character string")
test_error(serial_config("custom", "func1", "func2"), "must be functions")
test_error(serial_config("class", identity, identity, "wrong"), "must be a logical value")
test_error(opt(rep, "wrong") <- cfg, "not supported")
test_error(opt(rep, "serial") <- pairlist(a = 1L), "not supported")
test_error(opt(rep, "serial") <- list("wrong"), "Invalid argument")
test_error(opt(rep, "serial") <- list("class", identity, identity, "wrong"), "Invalid argument")
test_error(opt(rep, "serial") <- list("class", "wrong", function() {}, NA), "Invalid argument")
test_error(opt(rep, "serial") <- list("class", function() {}, "wrong", NA), "Invalid argument")

test_class("recvAio", cs <- request(req$context, "test", send_mode = "serial", cv = cv, timeout = 500))
test_notnull(cs$data)
Expand Down

0 comments on commit c522770

Please sign in to comment.