Skip to content

Commit

Permalink
add registered_types_internal and register_type for jruby implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
tagomoris committed Sep 8, 2015
1 parent 76ba902 commit b498368
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 22 deletions.
13 changes: 10 additions & 3 deletions ext/java/org/msgpack/jruby/Factory.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,16 @@ public Unpacker unpacker(ThreadContext ctx, IRubyObject[] args) {

@JRubyMethod(name = "registered_types_internal", visibility = PRIVATE)
public IRubyObject registeredTypesInternal(ThreadContext ctx) {
//TODO: unpackerExtRegistry
// IRubyObject[] ary = { packerRegistry().hash, unpackerRegistry().array };
IRubyObject[] ary = new IRubyObject[] {};
// unpacker
Unpacker.ExtRegistry reg = unpackerRegistry();
RubyHash mapping = RubyHash.newHash(ctx.getRuntime());
for (int i = 0; i < 256; i++) {
if (reg.array[i] != null) {
mapping.fastASet(RubyFixnum.newFixnum(ctx.getRuntime(), i - 128), reg.array[i]);
}
}

IRubyObject[] ary = { packerRegistry().hash, mapping };
return RubyArray.newArray(ctx.getRuntime(), ary);
}

Expand Down
51 changes: 47 additions & 4 deletions ext/java/org/msgpack/jruby/Packer.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,19 @@
import org.jruby.RubyIO;
import org.jruby.RubyInteger;
import org.jruby.RubyFixnum;
import org.jruby.runtime.Block;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.util.ByteList;

import static org.jruby.runtime.Visibility.PRIVATE;

@JRubyClass(name="MessagePack::Packer")
public class Packer extends RubyObject {
public ExtRegistry extRegistry;
public ExtRegistry registry;
private Buffer buffer;
private Encoder encoder;

Expand Down Expand Up @@ -99,11 +101,12 @@ public IRubyObject initialize(ThreadContext ctx, IRubyObject[] args) {
this.encoder = new Encoder(ctx.getRuntime(), compatibilityMode);
this.buffer = new Buffer(ctx.getRuntime(), ctx.getRuntime().getModule("MessagePack").getClass("Buffer"));
this.buffer.initialize(ctx, args);
this.registry = new ExtRegistry(ctx.getRuntime());
return this;
}

public void setExtRegistry(ExtRegistry registry) {
this.extRegistry = registry;
this.registry = registry;
this.encoder.setRegistry(registry);
}

Expand All @@ -114,8 +117,48 @@ public static Packer newPacker(ThreadContext ctx, ExtRegistry extRegistry, IRuby
return packer;
}

//TODO: registered_types_internal
//TODO: register_type
@JRubyMethod(name = "registered_types_internal", visibility = PRIVATE)
public IRubyObject registeredTypesInternal(ThreadContext ctx) {
////Nullpo
return this.registry.hash.dup(ctx);
}

@JRubyMethod(name = "register_type", required = 2, optional = 1)
public IRubyObject registerType(ThreadContext ctx, IRubyObject[] args, final Block block) {
// register_type(type, Class){|obj| how_to_serialize.... }
// register_type(type, Class, :to_msgpack_ext)
Ruby runtime = ctx.getRuntime();
IRubyObject type = args[0];
IRubyObject klass = args[1];

IRubyObject arg;
IRubyObject proc;
if (args.length == 2) {
if (! block.isGiven()) {
throw runtime.newLocalJumpErrorNoBlock();
}
proc = block.getProcObject();
arg = proc;
} else if (args.length == 3) {
arg = args[2];
proc = arg.callMethod(ctx, "to_proc");
} else {
throw runtime.newArgumentError(String.format("wrong number of arguments (%d for 2..3)", 2 + args.length));
}

long typeId = ((RubyFixnum) type).getLongValue();
if (typeId < -128 || typeId > 127) {
throw runtime.newRangeError(String.format("integer %d too big to convert to `signed char'", typeId));
}

if (!(klass instanceof RubyClass)) {
throw runtime.newArgumentError(String.format("expected Class but found %s.", klass.getType().getName()));
}
RubyClass extClass = (RubyClass) klass;

this.registry.put(extClass, (int) typeId, proc, arg);
return runtime.getNil();
}

@JRubyMethod(name = "write")
public IRubyObject write(ThreadContext ctx, IRubyObject obj) {
Expand Down
57 changes: 53 additions & 4 deletions ext/java/org/msgpack/jruby/Unpacker.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.jruby.RubyHash;
import org.jruby.RubyNumeric;
import org.jruby.RubyFixnum;
import org.jruby.RubyProc;
import org.jruby.RubyIO;
import org.jruby.exceptions.RaiseException;
import org.jruby.runtime.builtin.IRubyObject;
Expand All @@ -23,7 +24,6 @@

import static org.jruby.runtime.Visibility.PRIVATE;


@JRubyClass(name="MessagePack::Unpacker")
public class Unpacker extends RubyObject {
public ExtRegistry registry;
Expand Down Expand Up @@ -61,7 +61,11 @@ public ExtRegistry dup() {
}

public void put(RubyClass klass, int typeId, IRubyObject proc, IRubyObject arg) {
RubyArray e = RubyArray.newArray(runtime, new IRubyObject[] { RubyFixnum.newFixnum(runtime, typeId), proc, arg });
IRubyObject k = klass;
if (k == null) {
k = runtime.getNil();
}
RubyArray e = RubyArray.newArray(runtime, new IRubyObject[] { k, proc, arg });
array[typeId + 128] = e;
}

Expand Down Expand Up @@ -94,6 +98,7 @@ public IRubyObject initialize(ThreadContext ctx, IRubyObject[] args) {
setStream(ctx, args[0]);
}
}
this.registry = new ExtRegistry(ctx.getRuntime());
return this;
}

Expand All @@ -108,8 +113,52 @@ public static Unpacker newUnpacker(ThreadContext ctx, ExtRegistry extRegistry, I
return unpacker;
}

//TODO: registered_types_internal
//TODO: register_type
@JRubyMethod(name = "registered_types_internal", visibility = PRIVATE)
public IRubyObject registeredTypesInternal(ThreadContext ctx) {
RubyHash mapping = RubyHash.newHash(ctx.getRuntime());
for (int i = 0; i < 256; i++) {
if (registry.array[i] != null) {
mapping.fastASet(RubyFixnum.newFixnum(ctx.getRuntime(), i - 128), registry.array[i].dup());
}
}
return mapping;
}

@JRubyMethod(name = "register_type", required = 1, optional = 2)
public IRubyObject registerType(ThreadContext ctx, IRubyObject[] args, final Block block) {
// register_type(type){|data| ExtClass.deserialize(...) }
// register_type(type, Class, :from_msgpack_ext)
Ruby runtime = ctx.getRuntime();
IRubyObject type = args[0];

RubyClass extClass;
IRubyObject arg;
IRubyObject proc;
if (args.length == 1) {
if (! block.isGiven()) {
throw runtime.newLocalJumpErrorNoBlock();
}
proc = RubyProc.newProc(runtime, block, block.type);
if (proc == null)
System.err.println("proc from Block is null");
arg = proc;
extClass = null;
} else if (args.length == 3) {
extClass = (RubyClass) args[1];
arg = args[2];
proc = extClass.method(arg);
} else {
throw runtime.newArgumentError(String.format("wrong number of arguments (%d for 1 or 3)", 2 + args.length));
}

long typeId = ((RubyFixnum) type).getLongValue();
if (typeId < -128 || typeId > 127) {
throw runtime.newRangeError(String.format("integer %d too big to convert to `signed char'", typeId));
}

this.registry.put(extClass, (int) typeId, proc, arg);
return runtime.getNil();
}

@JRubyMethod(required = 2)
public IRubyObject execute(ThreadContext ctx, IRubyObject data, IRubyObject offset) {
Expand Down
2 changes: 1 addition & 1 deletion spec/msgpack_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def asciienc(str)
end

it 'rasies an error on #unpack with garbage' do
skip "???"
skip "but nothing was raised. why?"
expect { MessagePack.unpack('asdka;sd') }.to raise_error(MessagePack::UnpackError)
end
end
Expand Down
4 changes: 0 additions & 4 deletions spec/packer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,12 @@ def self.from_msgpack_ext(data)

describe '#type_registered?' do
it 'receive Class or Integer, and return bool' do
skip("not supported yet in JRuby implementation") if java?
expect(subject.type_registered?(0x00)).to be_falsy
expect(subject.type_registered?(0x01)).to be_falsy
expect(subject.type_registered?(::ValueOne)).to be_falsy
end

it 'returns true if specified type or class is already registered' do
skip("not supported yet in JRuby implementation") if java?
subject.register_type(0x30, ::ValueOne, :to_msgpack_ext)
subject.register_type(0x31, ::ValueTwo, :to_msgpack_ext)

Expand All @@ -56,7 +54,6 @@ def self.from_msgpack_ext(data)

describe '#register_type' do
it 'get type and class mapping for packing' do
skip("not supported yet in JRuby implementation") if java?
packer = MessagePack::Packer.new
packer.register_type(0x01, ValueOne){|obj| obj.to_msgpack_ext }
packer.register_type(0x02, ValueTwo){|obj| obj.to_msgpack_ext }
Expand All @@ -71,7 +68,6 @@ def self.from_msgpack_ext(data)
end

it 'returns a Hash which contains map of Class and type' do
skip("not supported yet in JRuby implementation") if java?
packer = MessagePack::Packer.new
packer.register_type(0x01, ValueOne, :to_msgpack_ext)
packer.register_type(0x02, ValueTwo, :to_msgpack_ext)
Expand Down
6 changes: 0 additions & 6 deletions spec/unpacker_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,12 @@ def self.from_msgpack_ext(data)

describe '#type_registered?' do
it 'receive Class or Integer, and return bool' do
skip("not supported yet in JRuby implementation") if java?
expect(subject.type_registered?(0x00)).to be_falsy
expect(subject.type_registered?(0x01)).to be_falsy
expect(subject.type_registered?(::ValueOne)).to be_falsy
end

it 'returns true if specified type or class is already registered' do
skip("not supported yet in JRuby implementation") if java?
subject.register_type(0x30, ::ValueOne, :from_msgpack_ext)
subject.register_type(0x31, ::ValueTwo, :from_msgpack_ext)

Expand All @@ -62,7 +60,6 @@ def self.from_msgpack_ext(data)
end

it 'cannot detect unpack rule with block, not method' do
skip("not supported yet in JRuby implementation") if java?
subject.register_type(0x40){|data| ValueOne.from_msgpack_ext(data) }

expect(subject.type_registered?(0x40)).to be_truthy
Expand All @@ -72,7 +69,6 @@ def self.from_msgpack_ext(data)

context 'with ext definitions' do
it 'get type and class mapping for packing' do
skip("not supported yet in JRuby implementation") if java?
unpacker = MessagePack::Unpacker.new
unpacker.register_type(0x01){|data| ValueOne.from_msgpack_ext }
unpacker.register_type(0x02){|data| ValueTwo.from_msgpack_ext(data) }
Expand All @@ -83,7 +79,6 @@ def self.from_msgpack_ext(data)
end

it 'returns a Array of Hash which contains :type, :class and :unpacker' do
skip("not supported yet in JRuby implementation") if java?
unpacker = MessagePack::Unpacker.new
unpacker.register_type(0x02, ValueTwo, :from_msgpack_ext)
unpacker.register_type(0x01, ValueOne, :from_msgpack_ext)
Expand All @@ -107,7 +102,6 @@ def self.from_msgpack_ext(data)
end

it 'returns a Array of Hash, which contains nil for class if block unpacker specified' do
skip("not supported yet in JRuby implementation") if java?
unpacker = MessagePack::Unpacker.new
unpacker.register_type(0x01){|data| ValueOne.from_msgpack_ext }
unpacker.register_type(0x02, &ValueTwo.method(:from_msgpack_ext))
Expand Down

0 comments on commit b498368

Please sign in to comment.