Skip to content

Commit d79406b

Browse files
committed
fix: support arrays in C++ join/leave
1 parent e0bfb56 commit d79406b

File tree

6 files changed

+59
-55
lines changed

6 files changed

+59
-55
lines changed

src/draft.ts

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,27 +41,28 @@ interface RadioGroupOptions {
4141
export interface Radio extends Writable<MessageLike, [RadioGroupOptions]> {}
4242
allowMethods(Radio.prototype, ["send"])
4343

44-
const join = (Socket.prototype as any).join
45-
const leave = (Socket.prototype as any).leave
44+
const join = (
45+
Socket.prototype as Socket & {
46+
join: (value: Array<string | Buffer>) => void
47+
}
48+
).join
49+
const leave = (
50+
Socket.prototype as Socket & {
51+
leave: (value: Array<string | Buffer>) => void
52+
}
53+
).leave
4654

4755
export class Dish extends Socket {
4856
constructor(options?: SocketOptions<Dish>) {
4957
super(SocketType.Dish, options)
5058
}
5159

52-
/* TODO: These methods might accept arrays in their C++ implementation for
53-
the sake of simplicity. */
54-
5560
join(...values: Array<Buffer | string>): void {
56-
for (const value of values) {
57-
join(value)
58-
}
61+
join(values)
5962
}
6063

6164
leave(...values: Array<Buffer | string>): void {
62-
for (const value of values) {
63-
leave(value)
64-
}
65+
leave(values)
6566
}
6667
}
6768

src/outgoing_msg.cc

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include "./module.h"
77
#include "util/error.h"
8+
#include "util/string_or_buffer.h"
89

910
namespace zmq {
1011
OutgoingMsg::OutgoingMsg(Napi::Value value, std::reference_wrapper<Module> module) {
@@ -116,18 +117,7 @@ bool OutgoingMsg::Parts::SetGroup(Napi::Value value) {
116117
return false;
117118
}
118119

119-
auto group = [&]() {
120-
if (value.IsString()) {
121-
return std::string(value.As<Napi::String>());
122-
}
123-
if (value.IsBuffer()) {
124-
auto buf = value.As<Napi::Object>();
125-
auto length = buf.As<Napi::Buffer<char>>().Length();
126-
auto* value = buf.As<Napi::Buffer<char>>().Data();
127-
return std::string(value, length);
128-
}
129-
return std::string();
130-
}();
120+
const auto group = convert_string_or_buffer(value);
131121

132122
for (auto& part : parts) {
133123
if (zmq_msg_set_group(part.get(), group.c_str()) < 0) {

src/socket.cc

Lines changed: 18 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "util/async_scope.h"
1515
#include "util/error.h"
1616
#include "util/object.h"
17+
#include "util/string_or_buffer.h"
1718
#include "util/take.h"
1819
#include "util/uvdelayed.h"
1920
#include "util/uvwork.h"
@@ -102,7 +103,7 @@ Socket::Socket(const Napi::CallbackInfo& info)
102103
return;
103104
}
104105

105-
uv_os_sock_t file_descriptor = 0;
106+
auto file_descriptor = uv_os_sock_t{};
106107

107108
const auto error = [this]() {
108109
[[maybe_unused]] auto err = zmq_close(socket);
@@ -751,27 +752,20 @@ Napi::Value Socket::Receive(const Napi::CallbackInfo& info) {
751752

752753
void Socket::Join([[maybe_unused]] const Napi::CallbackInfo& info) {
753754
#ifdef ZMQ_HAS_POLLABLE_THREAD_SAFE
754-
Arg::Validator args{
755-
Arg::Required<Arg::String, Arg::Buffer>("Group must be a string or buffer"),
756-
};
757-
758-
if (args.ThrowIfInvalid(info)) {
759-
return;
755+
for (size_t i_value = 0; i_value < info.Length(); ++i_value) {
756+
const auto& value = info[i_value];
757+
this->JoinElement(value);
760758
}
759+
#endif
760+
}
761761

762+
void Socket::JoinElement([[maybe_unused]] const Napi::Value& value) {
763+
#ifdef ZMQ_HAS_POLLABLE_THREAD_SAFE
762764
if (!ValidateOpen()) {
763765
return;
764766
}
765767

766-
auto str = [&]() {
767-
if (info[0].IsString()) {
768-
return std::string(info[0].As<Napi::String>());
769-
}
770-
auto buf = info[0].As<Napi::Object>();
771-
auto length = buf.As<Napi::Buffer<char>>().Length();
772-
auto* value = buf.As<Napi::Buffer<char>>().Data();
773-
return std::string(value, length);
774-
}();
768+
const auto str = convert_string_or_buffer(value);
775769

776770
if (zmq_join(socket, str.c_str()) < 0) {
777771
ErrnoException(Env(), zmq_errno()).ThrowAsJavaScriptException();
@@ -782,27 +776,20 @@ void Socket::Join([[maybe_unused]] const Napi::CallbackInfo& info) {
782776

783777
void Socket::Leave([[maybe_unused]] const Napi::CallbackInfo& info) {
784778
#ifdef ZMQ_HAS_POLLABLE_THREAD_SAFE
785-
Arg::Validator args{
786-
Arg::Required<Arg::String, Arg::Buffer>("Group must be a string or buffer"),
787-
};
788-
789-
if (args.ThrowIfInvalid(info)) {
790-
return;
779+
for (size_t i_value = 0; i_value < info.Length(); ++i_value) {
780+
const auto& value = info[i_value];
781+
this->LeaveElement(value);
791782
}
783+
#endif
784+
}
792785

786+
void Socket::LeaveElement([[maybe_unused]] const Napi::Value& value) {
787+
#ifdef ZMQ_HAS_POLLABLE_THREAD_SAFE
793788
if (!ValidateOpen()) {
794789
return;
795790
}
796791

797-
auto str = [&]() {
798-
if (info[0].IsString()) {
799-
return std::string(info[0].As<Napi::String>());
800-
}
801-
auto buf = info[0].As<Napi::Object>();
802-
auto length = buf.As<Napi::Buffer<char>>().Length();
803-
auto* value = buf.As<Napi::Buffer<char>>().Data();
804-
return std::string(value, length);
805-
}();
792+
const auto str = convert_string_or_buffer(value);
806793

807794
if (zmq_leave(socket, str.c_str()) < 0) {
808795
ErrnoException(Env(), zmq_errno()).ThrowAsJavaScriptException();

src/socket.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ class Socket : public Napi::ObjectWrap<Socket>, public Closable {
7373
force_inline void Send(const Napi::Promise::Deferred& res, OutgoingMsg::Parts& parts);
7474
force_inline void Receive(const Napi::Promise::Deferred& res);
7575

76+
inline void JoinElement(const Napi::Value& value);
77+
inline void LeaveElement(const Napi::Value& value);
78+
7679
class Poller : public zmq::Poller<Poller> {
7780
std::reference_wrapper<Socket> socket;
7881
std::optional<Napi::Promise::Deferred> read_deferred;

src/util/arguments.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ class Validator {
8888
if constexpr (I == NumArgs) {
8989
if (info.Length() > NumArgs) {
9090
auto msg = "Expected " + std::to_string(NumArgs) + " argument"
91-
+ (NumArgs != 1 ? "s" : "");
91+
+ (NumArgs != 1 ? "s" : "") + " but received "
92+
+ std::to_string(info.Length());
9293
return Napi::TypeError::New(info.Env(), msg);
9394
}
9495

src/util/string_or_buffer.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#pragma once
2+
3+
#include <napi.h>
4+
5+
#include <string>
6+
7+
namespace zmq {
8+
9+
inline std::string convert_string_or_buffer(const Napi::Value& value) {
10+
if (value.IsString()) {
11+
return std::string(value.As<Napi::String>());
12+
}
13+
if (value.IsBuffer()) {
14+
auto buf = value.As<Napi::Object>();
15+
auto length = buf.As<Napi::Buffer<char>>().Length();
16+
auto* value = buf.As<Napi::Buffer<char>>().Data();
17+
return {value, length};
18+
}
19+
throw Napi::TypeError::New(value.Env(), "Value must be a string or buffer");
20+
}
21+
22+
} // namespace zmq

0 commit comments

Comments
 (0)