ed-precompiled_nio4r 2.7.4-arm64-darwin

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,344 @@
1
+ /*
2
+ * Copyright (c) 2011 Tony Arcieri. Distributed under the MIT License. See
3
+ * LICENSE.txt for further details.
4
+ */
5
+
6
+ #include "nio4r.h"
7
+ #include <assert.h>
8
+
9
+ static VALUE mNIO = Qnil;
10
+ static VALUE cNIO_Monitor = Qnil;
11
+
12
+ /* Allocator/deallocator */
13
+ static VALUE NIO_Monitor_allocate(VALUE klass);
14
+ static void NIO_Monitor_mark(void *data);
15
+ static size_t NIO_Monitor_memsize(const void *data);
16
+
17
+ /* Methods */
18
+ static VALUE NIO_Monitor_initialize(VALUE self, VALUE selector, VALUE io, VALUE interests);
19
+ static VALUE NIO_Monitor_close(int argc, VALUE *argv, VALUE self);
20
+ static VALUE NIO_Monitor_is_closed(VALUE self);
21
+ static VALUE NIO_Monitor_io(VALUE self);
22
+ static VALUE NIO_Monitor_interests(VALUE self);
23
+ static VALUE NIO_Monitor_set_interests(VALUE self, VALUE interests);
24
+ static VALUE NIO_Monitor_add_interest(VALUE self, VALUE interest);
25
+ static VALUE NIO_Monitor_remove_interest(VALUE self, VALUE interest);
26
+ static VALUE NIO_Monitor_selector(VALUE self);
27
+ static VALUE NIO_Monitor_is_readable(VALUE self);
28
+ static VALUE NIO_Monitor_is_writable(VALUE self);
29
+ static VALUE NIO_Monitor_value(VALUE self);
30
+ static VALUE NIO_Monitor_set_value(VALUE self, VALUE obj);
31
+ static VALUE NIO_Monitor_readiness(VALUE self);
32
+
33
+ /* Internal C functions */
34
+ static int NIO_Monitor_symbol2interest(VALUE interests);
35
+ static void NIO_Monitor_update_interests(VALUE self, int interests);
36
+
37
+ /* Compatibility for Ruby <= 3.1 */
38
+ #ifndef HAVE_RB_IO_DESCRIPTOR
39
+ static int
40
+ io_descriptor_fallback(VALUE io)
41
+ {
42
+ rb_io_t *fptr;
43
+ GetOpenFile(io, fptr);
44
+ return fptr->fd;
45
+ }
46
+ #define rb_io_descriptor io_descriptor_fallback
47
+ #endif
48
+
49
+ /* Monitor control how a channel is being waited for by a monitor */
50
+ void Init_NIO_Monitor()
51
+ {
52
+ mNIO = rb_define_module("NIO");
53
+ cNIO_Monitor = rb_define_class_under(mNIO, "Monitor", rb_cObject);
54
+ rb_define_alloc_func(cNIO_Monitor, NIO_Monitor_allocate);
55
+
56
+ rb_define_method(cNIO_Monitor, "initialize", NIO_Monitor_initialize, 3);
57
+ rb_define_method(cNIO_Monitor, "close", NIO_Monitor_close, -1);
58
+ rb_define_method(cNIO_Monitor, "closed?", NIO_Monitor_is_closed, 0);
59
+ rb_define_method(cNIO_Monitor, "io", NIO_Monitor_io, 0);
60
+ rb_define_method(cNIO_Monitor, "interests", NIO_Monitor_interests, 0);
61
+ rb_define_method(cNIO_Monitor, "interests=", NIO_Monitor_set_interests, 1);
62
+ rb_define_method(cNIO_Monitor, "add_interest", NIO_Monitor_add_interest, 1);
63
+ rb_define_method(cNIO_Monitor, "remove_interest", NIO_Monitor_remove_interest, 1);
64
+ rb_define_method(cNIO_Monitor, "selector", NIO_Monitor_selector, 0);
65
+ rb_define_method(cNIO_Monitor, "value", NIO_Monitor_value, 0);
66
+ rb_define_method(cNIO_Monitor, "value=", NIO_Monitor_set_value, 1);
67
+ rb_define_method(cNIO_Monitor, "readiness", NIO_Monitor_readiness, 0);
68
+ rb_define_method(cNIO_Monitor, "readable?", NIO_Monitor_is_readable, 0);
69
+ rb_define_method(cNIO_Monitor, "writable?", NIO_Monitor_is_writable, 0);
70
+ rb_define_method(cNIO_Monitor, "writeable?", NIO_Monitor_is_writable, 0);
71
+ }
72
+
73
+ static const rb_data_type_t NIO_Monitor_type = {
74
+ "NIO::Monitor",
75
+ {
76
+ NIO_Monitor_mark,
77
+ RUBY_TYPED_DEFAULT_FREE,
78
+ NIO_Monitor_memsize,
79
+ },
80
+ 0,
81
+ 0,
82
+ RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
83
+ };
84
+
85
+ static VALUE NIO_Monitor_allocate(VALUE klass)
86
+ {
87
+ struct NIO_Monitor *monitor = (struct NIO_Monitor *)xmalloc(sizeof(struct NIO_Monitor));
88
+ assert(monitor);
89
+ *monitor = (struct NIO_Monitor){.self = Qnil};
90
+ return TypedData_Wrap_Struct(klass, &NIO_Monitor_type, monitor);
91
+ }
92
+
93
+ static void NIO_Monitor_mark(void *data)
94
+ {
95
+ struct NIO_Monitor *monitor = (struct NIO_Monitor *)data;
96
+ rb_gc_mark(monitor->self);
97
+ }
98
+
99
+ static size_t NIO_Monitor_memsize(const void *data)
100
+ {
101
+ const struct NIO_Monitor *monitor = (const struct NIO_Monitor *)data;
102
+ return sizeof(*monitor);
103
+ }
104
+
105
+ static VALUE NIO_Monitor_initialize(VALUE self, VALUE io, VALUE interests, VALUE selector_obj)
106
+ {
107
+ struct NIO_Monitor *monitor;
108
+ struct NIO_Selector *selector;
109
+ ID interests_id;
110
+
111
+ interests_id = SYM2ID(interests);
112
+
113
+ TypedData_Get_Struct(self, struct NIO_Monitor, &NIO_Monitor_type, monitor);
114
+
115
+ if (interests_id == rb_intern("r")) {
116
+ monitor->interests = EV_READ;
117
+ } else if (interests_id == rb_intern("w")) {
118
+ monitor->interests = EV_WRITE;
119
+ } else if (interests_id == rb_intern("rw")) {
120
+ monitor->interests = EV_READ | EV_WRITE;
121
+ } else {
122
+ rb_raise(rb_eArgError, "invalid event type %s (must be :r, :w, or :rw)", RSTRING_PTR(rb_funcall(interests, rb_intern("inspect"), 0)));
123
+ }
124
+
125
+ int descriptor = rb_io_descriptor(rb_convert_type(io, T_FILE, "IO", "to_io"));
126
+ ev_io_init(&monitor->ev_io, NIO_Selector_monitor_callback, descriptor, monitor->interests);
127
+
128
+ rb_ivar_set(self, rb_intern("io"), io);
129
+ rb_ivar_set(self, rb_intern("interests"), interests);
130
+ rb_ivar_set(self, rb_intern("selector"), selector_obj);
131
+
132
+ selector = NIO_Selector_unwrap(selector_obj);
133
+
134
+ RB_OBJ_WRITE(self, &monitor->self, self);
135
+ monitor->ev_io.data = (void *)monitor;
136
+
137
+ /* We can safely hang onto this as we also hang onto a reference to the
138
+ object where it originally came from */
139
+ monitor->selector = selector;
140
+
141
+ if (monitor->interests) {
142
+ ev_io_start(selector->ev_loop, &monitor->ev_io);
143
+ }
144
+
145
+ return Qnil;
146
+ }
147
+
148
+ static VALUE NIO_Monitor_close(int argc, VALUE *argv, VALUE self)
149
+ {
150
+ VALUE deregister, selector;
151
+ struct NIO_Monitor *monitor;
152
+ TypedData_Get_Struct(self, struct NIO_Monitor, &NIO_Monitor_type, monitor);
153
+
154
+ rb_scan_args(argc, argv, "01", &deregister);
155
+ selector = rb_ivar_get(self, rb_intern("selector"));
156
+
157
+ if (selector != Qnil) {
158
+ /* if ev_loop is 0, it means that the loop has been stopped already (see NIO_Selector_shutdown) */
159
+ if (monitor->interests && monitor->selector->ev_loop) {
160
+ ev_io_stop(monitor->selector->ev_loop, &monitor->ev_io);
161
+ }
162
+
163
+ monitor->selector = 0;
164
+ rb_ivar_set(self, rb_intern("selector"), Qnil);
165
+
166
+ /* Default value is true */
167
+ if (deregister == Qtrue || deregister == Qnil) {
168
+ rb_funcall(selector, rb_intern("deregister"), 1, rb_ivar_get(self, rb_intern("io")));
169
+ }
170
+ }
171
+
172
+ return Qnil;
173
+ }
174
+
175
+ static VALUE NIO_Monitor_is_closed(VALUE self)
176
+ {
177
+ struct NIO_Monitor *monitor;
178
+ TypedData_Get_Struct(self, struct NIO_Monitor, &NIO_Monitor_type, monitor);
179
+
180
+ return monitor->selector == 0 ? Qtrue : Qfalse;
181
+ }
182
+
183
+ static VALUE NIO_Monitor_io(VALUE self)
184
+ {
185
+ return rb_ivar_get(self, rb_intern("io"));
186
+ }
187
+
188
+ static VALUE NIO_Monitor_interests(VALUE self)
189
+ {
190
+ return rb_ivar_get(self, rb_intern("interests"));
191
+ }
192
+
193
+ static VALUE NIO_Monitor_set_interests(VALUE self, VALUE interests)
194
+ {
195
+ if (NIL_P(interests)) {
196
+ NIO_Monitor_update_interests(self, 0);
197
+ } else {
198
+ NIO_Monitor_update_interests(self, NIO_Monitor_symbol2interest(interests));
199
+ }
200
+
201
+ return rb_ivar_get(self, rb_intern("interests"));
202
+ }
203
+
204
+ static VALUE NIO_Monitor_add_interest(VALUE self, VALUE interest)
205
+ {
206
+ struct NIO_Monitor *monitor;
207
+ TypedData_Get_Struct(self, struct NIO_Monitor, &NIO_Monitor_type, monitor);
208
+
209
+ interest = monitor->interests | NIO_Monitor_symbol2interest(interest);
210
+ NIO_Monitor_update_interests(self, (int)interest);
211
+
212
+ return rb_ivar_get(self, rb_intern("interests"));
213
+ }
214
+
215
+ static VALUE NIO_Monitor_remove_interest(VALUE self, VALUE interest)
216
+ {
217
+ struct NIO_Monitor *monitor;
218
+ TypedData_Get_Struct(self, struct NIO_Monitor, &NIO_Monitor_type, monitor);
219
+
220
+ interest = monitor->interests & ~NIO_Monitor_symbol2interest(interest);
221
+ NIO_Monitor_update_interests(self, (int)interest);
222
+
223
+ return rb_ivar_get(self, rb_intern("interests"));
224
+ }
225
+
226
+ static VALUE NIO_Monitor_selector(VALUE self)
227
+ {
228
+ return rb_ivar_get(self, rb_intern("selector"));
229
+ }
230
+
231
+ static VALUE NIO_Monitor_value(VALUE self)
232
+ {
233
+ return rb_ivar_get(self, rb_intern("value"));
234
+ }
235
+
236
+ static VALUE NIO_Monitor_set_value(VALUE self, VALUE obj)
237
+ {
238
+ return rb_ivar_set(self, rb_intern("value"), obj);
239
+ }
240
+
241
+ static VALUE NIO_Monitor_readiness(VALUE self)
242
+ {
243
+ struct NIO_Monitor *monitor;
244
+ TypedData_Get_Struct(self, struct NIO_Monitor, &NIO_Monitor_type, monitor);
245
+
246
+ if ((monitor->revents & (EV_READ | EV_WRITE)) == (EV_READ | EV_WRITE)) {
247
+ return ID2SYM(rb_intern("rw"));
248
+ } else if (monitor->revents & EV_READ) {
249
+ return ID2SYM(rb_intern("r"));
250
+ } else if (monitor->revents & EV_WRITE) {
251
+ return ID2SYM(rb_intern("w"));
252
+ } else {
253
+ return Qnil;
254
+ }
255
+ }
256
+
257
+ static VALUE NIO_Monitor_is_readable(VALUE self)
258
+ {
259
+ struct NIO_Monitor *monitor;
260
+ TypedData_Get_Struct(self, struct NIO_Monitor, &NIO_Monitor_type, monitor);
261
+
262
+ if (monitor->revents & EV_READ) {
263
+ return Qtrue;
264
+ } else {
265
+ return Qfalse;
266
+ }
267
+ }
268
+
269
+ static VALUE NIO_Monitor_is_writable(VALUE self)
270
+ {
271
+ struct NIO_Monitor *monitor;
272
+ TypedData_Get_Struct(self, struct NIO_Monitor, &NIO_Monitor_type, monitor);
273
+
274
+ if (monitor->revents & EV_WRITE) {
275
+ return Qtrue;
276
+ } else {
277
+ return Qfalse;
278
+ }
279
+ }
280
+
281
+ /* Internal C functions */
282
+
283
+ static int NIO_Monitor_symbol2interest(VALUE interests)
284
+ {
285
+ ID interests_id;
286
+ interests_id = SYM2ID(interests);
287
+
288
+ if (interests_id == rb_intern("r")) {
289
+ return EV_READ;
290
+ } else if (interests_id == rb_intern("w")) {
291
+ return EV_WRITE;
292
+ } else if (interests_id == rb_intern("rw")) {
293
+ return EV_READ | EV_WRITE;
294
+ } else {
295
+ rb_raise(rb_eArgError, "invalid interest type %s (must be :r, :w, or :rw)", RSTRING_PTR(rb_funcall(interests, rb_intern("inspect"), 0)));
296
+ }
297
+ }
298
+
299
+ static void NIO_Monitor_update_interests(VALUE self, int interests)
300
+ {
301
+ ID interests_id;
302
+ struct NIO_Monitor *monitor;
303
+ TypedData_Get_Struct(self, struct NIO_Monitor, &NIO_Monitor_type, monitor);
304
+
305
+ if (NIO_Monitor_is_closed(self) == Qtrue) {
306
+ rb_raise(rb_eEOFError, "monitor is closed");
307
+ }
308
+
309
+ if (interests) {
310
+ switch (interests) {
311
+ case EV_READ:
312
+ interests_id = rb_intern("r");
313
+ break;
314
+ case EV_WRITE:
315
+ interests_id = rb_intern("w");
316
+ break;
317
+ case EV_READ | EV_WRITE:
318
+ interests_id = rb_intern("rw");
319
+ break;
320
+ default:
321
+ rb_raise(rb_eRuntimeError, "bogus NIO_Monitor_update_interests! (%d)", interests);
322
+ }
323
+
324
+ rb_ivar_set(self, rb_intern("interests"), ID2SYM(interests_id));
325
+ } else {
326
+ rb_ivar_set(self, rb_intern("interests"), Qnil);
327
+ }
328
+
329
+ if (monitor->interests != interests) {
330
+ // If the monitor currently has interests, we should stop it.
331
+ if (monitor->interests) {
332
+ ev_io_stop(monitor->selector->ev_loop, &monitor->ev_io);
333
+ }
334
+
335
+ // Assign the interests we are now monitoring for:
336
+ monitor->interests = interests;
337
+ ev_io_set(&monitor->ev_io, monitor->ev_io.fd, monitor->interests);
338
+
339
+ // If we are interested in events, schedule the monitor back into the event loop:
340
+ if (monitor->interests) {
341
+ ev_io_start(monitor->selector->ev_loop, &monitor->ev_io);
342
+ }
343
+ }
344
+ }
data/ext/nio4r/nio4r.h ADDED
@@ -0,0 +1,48 @@
1
+ /*
2
+ * Copyright (c) 2011 Tony Arcieri. Distributed under the MIT License. See
3
+ * LICENSE.txt for further details.
4
+ */
5
+
6
+ #ifndef NIO4R_H
7
+ #define NIO4R_H
8
+
9
+ #include "libev.h"
10
+ #include "ruby.h"
11
+ #include "ruby/io.h"
12
+
13
+ struct NIO_Selector {
14
+ struct ev_loop *ev_loop;
15
+ struct ev_timer timer; /* for timeouts */
16
+ struct ev_io wakeup;
17
+
18
+ int ready_count;
19
+ int closed, selecting;
20
+ int wakeup_reader, wakeup_writer;
21
+ volatile int wakeup_fired;
22
+
23
+ VALUE ready_array;
24
+ };
25
+
26
+ struct NIO_callback_data {
27
+ VALUE *monitor;
28
+ struct NIO_Selector *selector;
29
+ };
30
+
31
+ struct NIO_Monitor {
32
+ VALUE self;
33
+ int interests, revents;
34
+ struct ev_io ev_io;
35
+ struct NIO_Selector *selector;
36
+ };
37
+
38
+ struct NIO_ByteBuffer {
39
+ char *buffer;
40
+ int position, limit, capacity, mark;
41
+ };
42
+
43
+ struct NIO_Selector *NIO_Selector_unwrap(VALUE selector);
44
+
45
+ /* Thunk between libev callbacks in NIO::Monitors and NIO::Selectors */
46
+ void NIO_Selector_monitor_callback(struct ev_loop *ev_loop, struct ev_io *io, int revents);
47
+
48
+ #endif /* NIO4R_H */
@@ -0,0 +1,24 @@
1
+ /*
2
+ * Copyright (c) 2011-2017 Tony Arcieri. Distributed under the MIT License.
3
+ * See LICENSE.txt for further details.
4
+ */
5
+
6
+ #include "../libev/ev.c"
7
+ #include "nio4r.h"
8
+
9
+ void Init_NIO_Selector();
10
+ void Init_NIO_Monitor();
11
+ void Init_NIO_ByteBuffer();
12
+
13
+ void Init_nio4r_ext()
14
+ {
15
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
16
+ rb_ext_ractor_safe(true);
17
+ #endif
18
+
19
+ ev_set_allocator(xrealloc);
20
+
21
+ Init_NIO_Selector();
22
+ Init_NIO_Monitor();
23
+ Init_NIO_ByteBuffer();
24
+ }
@@ -0,0 +1,295 @@
1
+ package org.nio4r;
2
+
3
+ import java.io.IOException;
4
+ import java.io.Serializable;
5
+ import java.nio.channels.Channel;
6
+ import java.nio.channels.SelectableChannel;
7
+ import java.nio.channels.ReadableByteChannel;
8
+ import java.nio.channels.WritableByteChannel;
9
+ import java.nio.BufferOverflowException;
10
+ import java.nio.BufferUnderflowException;
11
+ import java.nio.InvalidMarkException;
12
+
13
+ import org.jruby.Ruby;
14
+ import org.jruby.RubyClass;
15
+ import org.jruby.RubyIO;
16
+ import org.jruby.RubyNumeric;
17
+ import org.jruby.RubyObject;
18
+ import org.jruby.RubyString;
19
+ import org.jruby.anno.JRubyMethod;
20
+ import org.jruby.exceptions.RaiseException;
21
+ import org.jruby.runtime.ThreadContext;
22
+ import org.jruby.runtime.builtin.IRubyObject;
23
+ import org.jruby.runtime.Block;
24
+
25
+ /*
26
+ created by Upekshej
27
+ */
28
+ public class ByteBuffer extends RubyObject {
29
+ private static final long serialVersionUID = -6903439483039149324L;
30
+ private transient java.nio.ByteBuffer byteBuffer;
31
+
32
+ public static RaiseException newOverflowError(ThreadContext context, String message) {
33
+ RubyClass klass = context.runtime.getModule("NIO").getClass("ByteBuffer").getClass("OverflowError");
34
+ return context.runtime.newRaiseException(klass, message);
35
+ }
36
+
37
+ public static RaiseException newUnderflowError(ThreadContext context, String message) {
38
+ RubyClass klass = context.runtime.getModule("NIO").getClass("ByteBuffer").getClass("UnderflowError");
39
+ return context.runtime.newRaiseException(klass, message);
40
+ }
41
+
42
+ public static RaiseException newMarkUnsetError(ThreadContext context, String message) {
43
+ RubyClass klass = context.runtime.getModule("NIO").getClass("ByteBuffer").getClass("MarkUnsetError");
44
+ return context.runtime.newRaiseException(klass, message);
45
+ }
46
+
47
+ public ByteBuffer(final Ruby ruby, RubyClass rubyClass) {
48
+ super(ruby, rubyClass);
49
+ }
50
+
51
+ @JRubyMethod
52
+ public IRubyObject initialize(ThreadContext context, IRubyObject capacity) {
53
+ this.byteBuffer = java.nio.ByteBuffer.allocate(RubyNumeric.num2int(capacity));
54
+ return this;
55
+ }
56
+
57
+ @JRubyMethod
58
+ public IRubyObject clear(ThreadContext context) {
59
+ this.byteBuffer.clear();
60
+ return this;
61
+ }
62
+
63
+ @JRubyMethod(name = "position")
64
+ public IRubyObject getPosition(ThreadContext context) {
65
+ return context.getRuntime().newFixnum(this.byteBuffer.position());
66
+ }
67
+
68
+ @JRubyMethod(name = "position=")
69
+ public IRubyObject setPosition(ThreadContext context, IRubyObject newPosition) {
70
+ int pos = RubyNumeric.num2int(newPosition);
71
+
72
+ if(pos < 0) {
73
+ throw context.runtime.newArgumentError("negative position given");
74
+ }
75
+
76
+ if(pos > this.byteBuffer.limit()) {
77
+ throw context.runtime.newArgumentError("specified position exceeds limit");
78
+ }
79
+
80
+ try {
81
+ this.byteBuffer.position(pos);
82
+ return newPosition;
83
+ } catch(IllegalArgumentException e) {
84
+ throw context.runtime.newArgumentError(e.getLocalizedMessage());
85
+ }
86
+ }
87
+
88
+ @JRubyMethod(name = "limit")
89
+ public IRubyObject getLimit(ThreadContext context) {
90
+ return context.getRuntime().newFixnum(this.byteBuffer.limit());
91
+ }
92
+
93
+ @JRubyMethod(name = "limit=")
94
+ public IRubyObject setLimit(ThreadContext context, IRubyObject newLimit) {
95
+ int lim = RubyNumeric.num2int(newLimit);
96
+
97
+ if(lim < 0) {
98
+ throw context.runtime.newArgumentError("negative limit given");
99
+ }
100
+
101
+ if(lim > this.byteBuffer.capacity()) {
102
+ throw context.runtime.newArgumentError("specified limit exceeds capacity");
103
+ }
104
+
105
+ try {
106
+ this.byteBuffer.limit(lim);
107
+ return newLimit;
108
+ } catch(IllegalArgumentException e) {
109
+ throw context.runtime.newArgumentError(e.getLocalizedMessage());
110
+ }
111
+ }
112
+
113
+ @JRubyMethod(name = {"capacity", "size"})
114
+ public IRubyObject capacity(ThreadContext context) {
115
+ return context.getRuntime().newFixnum(this.byteBuffer.capacity());
116
+ }
117
+
118
+ @JRubyMethod
119
+ public IRubyObject remaining(ThreadContext context) {
120
+ return context.getRuntime().newFixnum(this.byteBuffer.remaining());
121
+ }
122
+
123
+ @JRubyMethod(name = "full?")
124
+ public IRubyObject isFull(ThreadContext context) {
125
+ if (this.byteBuffer.hasRemaining()) {
126
+ return context.getRuntime().getFalse();
127
+ } else {
128
+ return context.getRuntime().getTrue();
129
+ }
130
+ }
131
+
132
+ @JRubyMethod
133
+ public IRubyObject get(ThreadContext context) {
134
+ return this.get(context, context.getRuntime().newFixnum(this.byteBuffer.remaining()));
135
+ }
136
+
137
+ @JRubyMethod
138
+ public IRubyObject get(ThreadContext context, IRubyObject length) {
139
+ int len = RubyNumeric.num2int(length);
140
+ byte[] bytes = new byte[len];
141
+
142
+ try {
143
+ this.byteBuffer.get(bytes);
144
+ } catch(BufferUnderflowException e) {
145
+ throw ByteBuffer.newUnderflowError(context, "not enough data in buffer");
146
+ }
147
+
148
+ return RubyString.newString(context.getRuntime(), bytes);
149
+ }
150
+
151
+ @JRubyMethod(name = "[]")
152
+ public IRubyObject fetch(ThreadContext context, IRubyObject index) {
153
+ int i = RubyNumeric.num2int(index);
154
+
155
+ if(i < 0) {
156
+ throw context.runtime.newArgumentError("negative index given");
157
+ }
158
+
159
+ if(i >= this.byteBuffer.limit()) {
160
+ throw context.runtime.newArgumentError("index exceeds limit");
161
+ }
162
+
163
+ return context.getRuntime().newFixnum(this.byteBuffer.get(i));
164
+ }
165
+
166
+ @JRubyMethod(name = "<<")
167
+ public IRubyObject put(ThreadContext context, IRubyObject str) {
168
+ try {
169
+ this.byteBuffer.put(str.convertToString().getByteList().bytes());
170
+ } catch(BufferOverflowException e) {
171
+ throw ByteBuffer.newOverflowError(context, "buffer is full");
172
+ }
173
+
174
+ return this;
175
+ }
176
+
177
+ @JRubyMethod(name = "read_from")
178
+ public IRubyObject readFrom(ThreadContext context, IRubyObject io) {
179
+ Ruby runtime = context.runtime;
180
+ Channel channel = RubyIO.convertToIO(context, io).getChannel();
181
+
182
+ if(!this.byteBuffer.hasRemaining()) {
183
+ throw ByteBuffer.newOverflowError(context, "buffer is full");
184
+ }
185
+
186
+ if(!(channel instanceof ReadableByteChannel) || !(channel instanceof SelectableChannel)) {
187
+ throw runtime.newArgumentError("unsupported IO object: " + io.getType().toString());
188
+ }
189
+
190
+ try {
191
+ ((SelectableChannel)channel).configureBlocking(false);
192
+ } catch(IOException ie) {
193
+ throw runtime.newIOError(ie.getLocalizedMessage());
194
+ }
195
+
196
+ try {
197
+ int bytesRead = ((ReadableByteChannel)channel).read(this.byteBuffer);
198
+
199
+ if(bytesRead >= 0) {
200
+ return runtime.newFixnum(bytesRead);
201
+ } else {
202
+ throw runtime.newEOFError();
203
+ }
204
+ } catch(IOException ie) {
205
+ throw runtime.newIOError(ie.getLocalizedMessage());
206
+ }
207
+ }
208
+
209
+ @JRubyMethod(name = "write_to")
210
+ public IRubyObject writeTo(ThreadContext context, IRubyObject io) {
211
+ Ruby runtime = context.runtime;
212
+ Channel channel = RubyIO.convertToIO(context, io).getChannel();
213
+
214
+ if(!this.byteBuffer.hasRemaining()) {
215
+ throw ByteBuffer.newUnderflowError(context, "not enough data in buffer");
216
+ }
217
+
218
+ if(!(channel instanceof WritableByteChannel) || !(channel instanceof SelectableChannel)) {
219
+ throw runtime.newArgumentError("unsupported IO object: " + io.getType().toString());
220
+ }
221
+
222
+ try {
223
+ ((SelectableChannel)channel).configureBlocking(false);
224
+ } catch(IOException ie) {
225
+ throw runtime.newIOError(ie.getLocalizedMessage());
226
+ }
227
+
228
+ try {
229
+ int bytesWritten = ((WritableByteChannel)channel).write(this.byteBuffer);
230
+
231
+ if(bytesWritten >= 0) {
232
+ return runtime.newFixnum(bytesWritten);
233
+ } else {
234
+ throw runtime.newEOFError();
235
+ }
236
+ } catch(IOException ie) {
237
+ throw runtime.newIOError(ie.getLocalizedMessage());
238
+ }
239
+ }
240
+
241
+ @JRubyMethod
242
+ public IRubyObject flip(ThreadContext context) {
243
+ this.byteBuffer.flip();
244
+ return this;
245
+ }
246
+
247
+ @JRubyMethod
248
+ public IRubyObject rewind(ThreadContext context) {
249
+ this.byteBuffer.rewind();
250
+ return this;
251
+ }
252
+
253
+ @JRubyMethod
254
+ public IRubyObject mark(ThreadContext context) {
255
+ this.byteBuffer.mark();
256
+ return this;
257
+ }
258
+
259
+ @JRubyMethod
260
+ public IRubyObject reset(ThreadContext context) {
261
+ try {
262
+ this.byteBuffer.reset();
263
+ return this;
264
+ } catch(InvalidMarkException ie) {
265
+ throw ByteBuffer.newMarkUnsetError(context, "mark has not been set");
266
+ }
267
+ }
268
+
269
+ @JRubyMethod
270
+ public IRubyObject compact(ThreadContext context) {
271
+ this.byteBuffer.compact();
272
+ return this;
273
+ }
274
+
275
+ @JRubyMethod
276
+ public IRubyObject each(ThreadContext context, Block block) {
277
+ for(int i = 0; i < this.byteBuffer.limit(); i++) {
278
+ block.call(context, context.getRuntime().newFixnum(this.byteBuffer.get(i)));
279
+ }
280
+
281
+ return this;
282
+ }
283
+
284
+ @JRubyMethod
285
+ public IRubyObject inspect(ThreadContext context) {
286
+ return context.runtime.newString(String.format(
287
+ "#<%s:0x%x @position=%d @limit=%d @capacity=%d>",
288
+ this.getType().toString(),
289
+ System.identityHashCode(this),
290
+ this.byteBuffer.position(),
291
+ this.byteBuffer.limit(),
292
+ this.byteBuffer.capacity()
293
+ ));
294
+ }
295
+ }