Skip to content

Commit 280951b

Browse files
committed
Disable partial matching for 'mode' argument
1 parent f58c51d commit 280951b

File tree

3 files changed

+96
-88
lines changed

3 files changed

+96
-88
lines changed

NEWS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#### Updates
1515

16+
* Partial matching is no longer enabled for the 'mode' argument to send/receive functions.
1617
* `send_aio()` without keeping a reference to the return value no longer potentially drops sends (thanks @wch, #129).
1718
* More robust interruption on non-Windows platforms when `tools::SIGINT` is supplied to the `flag` argument of `pipe_notify()` (thanks @LennardLux, #97).
1819
* Installation from source specifying 'INCLUDE_DIR' and 'LIB_DIR' environment variables works again, correcting a regression in v1.5.2 (#104).

src/core.c

Lines changed: 78 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -534,93 +534,100 @@ void nano_encode(nano_buf *enc, const SEXP object) {
534534

535535
int nano_encodes(const SEXP mode) {
536536

537-
if (TYPEOF(mode) != INTSXP) {
538-
const char *mod = CHAR(STRING_ELT(mode, 0));
539-
size_t slen = strlen(mod);
540-
switch (slen) {
541-
case 1:
542-
case 2:
543-
case 3:
544-
if (!memcmp(mod, "raw", slen)) return 2;
545-
case 4:
546-
case 5:
547-
case 6:
548-
if (!memcmp(mod, "serial", slen)) return 1;
549-
default:
550-
Rf_error("'mode' should be either serial or raw");
551-
}
537+
if (TYPEOF(mode) == INTSXP)
538+
return NANO_INTEGER(mode);
539+
540+
const char *mod = CHAR(STRING_ELT(mode, 0));
541+
size_t slen = strlen(mod);
542+
int i;
543+
switch (slen) {
544+
case 3:
545+
if (!memcmp(mod, "raw", slen)) { i = 2; break; }
546+
goto fail;
547+
case 6:
548+
if (!memcmp(mod, "serial", slen)) { i = 1; break; }
549+
goto fail;
550+
default:
551+
goto fail;
552552
}
553553

554-
return INTEGER(mode)[0];
554+
return i;
555+
556+
fail:
557+
Rf_error("'mode' should be either serial or raw");
555558

556559
}
557560

558561
int nano_matcharg(const SEXP mode) {
559562

560-
if (TYPEOF(mode) != INTSXP) {
561-
const char *mod = CHAR(STRING_ELT(mode, 0));
562-
size_t slen = strlen(mod);
563-
switch (slen) {
564-
case 1:
565-
if (!memcmp(mod, "c", slen) || !memcmp(mod, "s", slen))
566-
Rf_error("'mode' should be one of serial, character, complex, double, integer, logical, numeric, raw, string");
567-
case 2:
568-
case 3:
569-
if (!memcmp(mod, "raw", slen)) return 8;
570-
case 4:
571-
case 5:
572-
case 6:
573-
if (!memcmp(mod, "double", slen)) return 4;
574-
if (!memcmp(mod, "serial", slen)) return 1;
575-
if (!memcmp(mod, "string", slen)) return 9;
576-
case 7:
577-
if (!memcmp(mod, "integer", slen)) return 5;
578-
if (!memcmp(mod, "numeric", slen)) return 7;
579-
if (!memcmp(mod, "logical", slen)) return 6;
580-
if (!memcmp(mod, "complex", slen)) return 3;
581-
case 8:
582-
case 9:
583-
if (!memcmp(mod, "character", slen)) return 2;
584-
default:
585-
Rf_error("'mode' should be one of serial, character, complex, double, integer, logical, numeric, raw, string");
586-
}
563+
if (TYPEOF(mode) == INTSXP)
564+
return NANO_INTEGER(mode);
565+
566+
const char *mod = CHAR(STRING_ELT(mode, 0));
567+
size_t slen = strlen(mod);
568+
int i;
569+
switch (slen) {
570+
case 3:
571+
if (!memcmp(mod, "raw", slen)) { i = 8; break; }
572+
goto fail;
573+
case 6:
574+
if (!memcmp(mod, "serial", slen)) { i = 1; break; }
575+
if (!memcmp(mod, "double", slen)) { i = 4; break; }
576+
if (!memcmp(mod, "string", slen)) { i = 9; break; }
577+
goto fail;
578+
case 7:
579+
if (!memcmp(mod, "integer", slen)) { i = 5; break; }
580+
if (!memcmp(mod, "numeric", slen)) { i = 7; break; }
581+
if (!memcmp(mod, "logical", slen)) { i = 6; break; }
582+
if (!memcmp(mod, "complex", slen)) { i = 3; break; }
583+
goto fail;
584+
case 9:
585+
if (!memcmp(mod, "character", slen)) { i = 2; break; }
586+
goto fail;
587+
default:
588+
goto fail;
587589
}
588590

589-
return INTEGER(mode)[0];
591+
return i;
592+
593+
fail:
594+
Rf_error("'mode' should be one of serial, character, complex, double, integer, logical, numeric, raw, string");
590595

591596
}
592597

593598
int nano_matchargs(const SEXP mode) {
594599

595-
if (TYPEOF(mode) != INTSXP) {
596-
const char *mod = CHAR(STRING_ELT(mode, XLENGTH(mode) == 9));
597-
size_t slen = strlen(mod);
598-
switch (slen) {
599-
case 1:
600-
if (!memcmp(mod, "c", slen))
601-
Rf_error("'mode' should be one of character, complex, double, integer, logical, numeric, raw, string");
602-
case 2:
603-
case 3:
604-
if (!memcmp(mod, "raw", slen)) return 8;
605-
case 4:
606-
case 5:
607-
case 6:
608-
if (!memcmp(mod, "double", slen)) return 4;
609-
if (!memcmp(mod, "string", slen)) return 9;
610-
case 7:
611-
if (!memcmp(mod, "integer", slen)) return 5;
612-
if (!memcmp(mod, "numeric", slen)) return 7;
613-
if (!memcmp(mod, "logical", slen)) return 6;
614-
if (!memcmp(mod, "complex", slen)) return 3;
615-
case 8:
616-
case 9:
617-
if (!memcmp(mod, "character", slen)) return 2;
618-
default:
619-
Rf_error("'mode' should be one of character, complex, double, integer, logical, numeric, raw, string");
620-
}
600+
if (TYPEOF(mode) == INTSXP)
601+
return NANO_INTEGER(mode);
602+
603+
const char *mod = CHAR(STRING_ELT(mode, XLENGTH(mode) == 9));
604+
size_t slen = strlen(mod);
605+
int i;
606+
switch (slen) {
607+
case 3:
608+
if (!memcmp(mod, "raw", slen)) { i = 8; break; }
609+
goto fail;
610+
case 6:
611+
if (!memcmp(mod, "double", slen)) { i = 4; break; }
612+
if (!memcmp(mod, "string", slen)) { i = 9; break; }
613+
goto fail;
614+
case 7:
615+
if (!memcmp(mod, "integer", slen)) { i = 5; break; }
616+
if (!memcmp(mod, "numeric", slen)) { i = 7; break; }
617+
if (!memcmp(mod, "logical", slen)) { i = 6; break; }
618+
if (!memcmp(mod, "complex", slen)) { i = 3; break; }
619+
goto fail;
620+
case 9:
621+
if (!memcmp(mod, "character", slen)) { i = 2; break; }
622+
goto fail;
623+
default:
624+
goto fail;
621625
}
622626

623-
return INTEGER(mode)[0];
627+
return i;
628+
629+
fail:
630+
Rf_error("'mode' should be one of character, complex, double, integer, logical, numeric, raw, string");
624631

625632
}
626633

tests/tests.R

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ test_equal(n1$dialer[[1]]$state, "started")
7070

7171
test_error(n$send(list(), mode = "raw"), "atomic vector type")
7272
test_error(n$recv(mode = "none"), "mode")
73-
test_error(n$recv(mode = "c"), "mode")
73+
test_error(n$recv(mode = "charac"), "mode")
7474
test_true(is_aio(raio <- n1$recv_aio(timeout = 1L)))
7575
test_print(raio)
7676
test_class("errorValue", call_aio(raio)$data)
@@ -84,8 +84,8 @@ if (is_error_value(r)) r <- n1$recv(block = 500)
8484
test_class("data.frame", r)
8585
test_zero(n1$send(c("test", "", "spec"), mode = "raw", block = 500))
8686
test_identical(n$recv("character", block = 500), c("test", "", "spec"))
87-
test_zero(n$send(1:5, mode = "r"))
88-
test_equal(length(n1$recv("int", block = 500)), 5L)
87+
test_zero(n$send(1:5, mode = "raw"))
88+
test_equal(length(n1$recv("integer", block = 500)), 5L)
8989
test_true(is_aio(saio <- n1$send_aio(paste(replicate(5, random(1e3L)), collapse = ""), mode = 1L, timeout = 900)))
9090
test_print(saio)
9191
if (later) test_null(.keep(saio, new.env()))
@@ -103,37 +103,37 @@ saio$newfield <- "doesnotwork"
103103
test_null(saio$newfield)
104104
test_type("logical", unresolved(saio))
105105
test_type("logical", .unresolved(saio))
106-
test_class("recvAio", msg <- n1$recv_aio(mode = "numer", timeout = 500))
106+
test_class("recvAio", msg <- n1$recv_aio(mode = "numeric", timeout = 500))
107107
test_identical(call_aio(msg), msg)
108108
test_class("recvAio", msg <- n1$recv_aio(mode = "complex", timeout = 500))
109109
test_null(stop_aio(msg))
110110
test_null(stop_aio(n))
111111
test_identical(call_aio(msg), msg)
112112
test_class("errorValue", msg$data)
113113
test_identical(call_aio(n), n)
114-
test_class("sendAio", sraio <- n$send_aio(as.raw(0L), mode = "r", timeout = 500))
114+
test_class("sendAio", sraio <- n$send_aio(as.raw(0L), mode = "raw", timeout = 500))
115115
test_class("recvAio", rraio <- n1$recv_aio(mode = 1L, timeout = 500))
116116
test_true(is_nul_byte(suppressWarnings(call_aio_(rraio)$data)))
117-
test_class("sendAio", sraio <- n$send_aio(as.raw(1L), mode = "ra", timeout = 500))
117+
test_class("sendAio", sraio <- n$send_aio(as.raw(1L), mode = 2L, timeout = 500))
118118
test_class("recvAio", rraio <- n1$recv_aio(mode = "raw", timeout = 500))
119119
test_type("raw", call_aio(rraio)$data)
120120
test_class("sendAio", sraio <- n$send_aio(c(1+2i, 4+3i), mode = "raw", timeout = 500))
121-
test_class("recvAio", rraio <- n1$recv_aio(mode = "co", timeout = 500))
121+
test_class("recvAio", rraio <- n1$recv_aio(mode = "complex", timeout = 500))
122122
test_type("complex", call_aio(rraio)$data)
123123
test_class("sendAio", sraio <- n$send_aio(5, mode = "raw", timeout = 500))
124-
test_class("recvAio", rraio <- n1$recv_aio(mode = "d", timeout = 500))
124+
test_class("recvAio", rraio <- n1$recv_aio(mode = "double", timeout = 500))
125125
test_type("double", call_aio(rraio)$data)
126126
test_class("sendAio", sraio <- n$send_aio(c(1, 2), mode = "raw", timeout = 500))
127-
test_class("recvAio", rraio <- n1$recv_aio(mode = "n", timeout = 500))
127+
test_class("recvAio", rraio <- n1$recv_aio(mode = "numeric", timeout = 500))
128128
test_true(is.numeric(call_aio(rraio)$data))
129129
test_class("sendAio", sraio <- n$send_aio(c(1L, 2L, 3L), mode = "raw", timeout = 500))
130-
test_class("recvAio", rraio <- n1$recv_aio(mode = "i", timeout = 500))
130+
test_class("recvAio", rraio <- n1$recv_aio(mode = "integer", timeout = 500))
131131
test_type("integer", call_aio(rraio)$data)
132132
test_class("sendAio", sraio <- n$send_aio(as.raw(0L), mode = "raw", timeout = 500))
133133
test_class("recvAio", rraio <- n1$recv_aio(mode = "double", timeout = 500))
134134
test_type("raw", suppressWarnings(call_aio(rraio)$data))
135135
test_class("sendAio", sraio <- n$send_aio(as.raw(0L), mode = "raw", timeout = 500))
136-
test_class("recvAio", rraio <- n1$recv_aio(mode = "int", timeout = 500))
136+
test_class("recvAio", rraio <- n1$recv_aio(mode = "integer", timeout = 500))
137137
test_type("raw", suppressWarnings(call_aio(rraio)$data))
138138
test_class("sendAio", sraio <- n$send_aio(as.raw(0L), mode = "raw", timeout = 500))
139139
test_class("recvAio", rraio <- n1$recv_aio(mode = "logical", timeout = 500))
@@ -210,7 +210,7 @@ test_class("nanoContext", ctx <- context(rep))
210210
test_print(ctx)
211211
test_equal(.header(12345L), 12345L)
212212
test_true(.mark())
213-
test_class("sendAio", csaio <- req$send_aio(data.frame(), mode = "seria", timeout = 500))
213+
test_class("sendAio", csaio <- req$send_aio(data.frame(), mode = 1L, timeout = 500))
214214
test_zero(call_aio_(csaio)$result)
215215
test_class("recvAio", craio <- recv_aio(ctx, mode = 8L, timeout = 500))
216216
test_type("raw", res <- collect_aio(craio))
@@ -223,8 +223,8 @@ test_equal(.header(0L), 0L)
223223
test_true(!.mark(FALSE))
224224
test_zero(req$send("context test", mode ="raw", block = 500))
225225
test_equal(recv(ctx, mode = "string", block = 500), "context test")
226-
test_type("integer", req$send(data.frame(), mode = "seri", block = 500))
227-
test_class("recvAio", msg <- recv_aio(ctx, mode = "ser", timeout = 500))
226+
test_type("integer", req$send(data.frame(), mode = "serial", block = 500))
227+
test_class("recvAio", msg <- recv_aio(ctx, mode = "serial", timeout = 500))
228228
test_type("logical", .unresolved(msg))
229229
test_type("logical", unresolved(msg))
230230
test_class("data.frame", call_aio(msg)$data)
@@ -249,7 +249,7 @@ test_null(call_aio(recv_aio(ctx, mode = 1L, timeout = 500))[["value"]])
249249
test_class("sendAio", saio <- send_aio(ctx, as.raw(1L), mode = 2L, timeout = 500))
250250
test_identical(req$recv(mode = 8L, block = 500), as.raw(1L))
251251
test_class("recvAio", rek <- request(req$context, c(1+3i, 4+2i), send_mode = 2L, recv_mode = "complex", timeout = 500))
252-
test_zero(reply(ctx, execute = identity, recv_mode = 3L, send_mode = "ra", timeout = 500))
252+
test_zero(reply(ctx, execute = identity, recv_mode = 3L, send_mode = "raw", timeout = 500))
253253
test_type("complex", call_aio(rek)[["data"]])
254254
test_class("recvAio", rek <- request(req$context, c(1+3i, 4+2i), send_mode = "serial", recv_mode = "serial", timeout = 500))
255255
test_zero(reply(ctx, execute = identity, recv_mode = 1L, send_mode = 1L, timeout = 500))
@@ -505,7 +505,7 @@ if (is_nano(s)) test_notnull(recv(s, block = FALSE))
505505
if (is_nano(s)) test_type("integer", send(s, "message2", block = FALSE))
506506
if (is_nano(s)) test_notnull(suppressWarnings(recv(s, mode = 9L, block = 100)))
507507
if (is_nano(s)) test_type("integer", send(s, 2L, block = 500))
508-
if (is_nano(s)) test_class("recvAio", sr <- recv_aio(s, mode = "i", timeout = 500L, n = 8192L))
508+
if (is_nano(s)) test_class("recvAio", sr <- recv_aio(s, mode = "integer", timeout = 500L, n = 8192L))
509509
if (is_nano(s)) test_notnull(suppressWarnings(call_aio(sr)[["data"]]))
510510
if (is_nano(s)) test_null(stop_aio(sr))
511511
if (is_nano(s)) test_class("sendAio", ss <- send_aio(s, "async", timeout = 500L))
@@ -518,7 +518,7 @@ if (is_nano(s)) test_true(cv_value(cv) > 0L)
518518
if (is_nano(s)) test_type("character", opt(s, "ws:request-headers"))
519519
if (is_nano(s)) test_notnull(opt(s, "tcp-nodelay") <- FALSE)
520520
if (is_nano(s)) test_error(recv(s, mode = "none", block = FALSE), "should be one of character")
521-
if (is_nano(s)) test_error(recv(s, mode = "c", block = FALSE), "should be one of character")
521+
if (is_nano(s)) test_error(recv(s, mode = "charac", block = FALSE), "should be one of character")
522522
if (is_nano(s)) test_error(opt(s, "none"), "supported")
523523
if (is_nano(s)) test_error(`opt<-`(s, "none", list()), "supported")
524524
if (is_nano(s)) test_print(s)

0 commit comments

Comments
 (0)