package org.msgpack.jruby;


import org.jruby.Ruby;
import org.jruby.RubyModule;
import org.jruby.RubyClass;
import org.jruby.RubyString;
import org.jruby.RubyHash;
import org.jruby.runtime.load.Library;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.ThreadContext;
import org.jruby.anno.JRubyModule;
import org.jruby.anno.JRubyMethod;


public class MessagePackLibrary implements Library {
  public void load(Ruby runtime, boolean wrap) {
    RubyModule msgpackModule = runtime.defineModule("MessagePack");
    msgpackModule.defineAnnotatedMethods(MessagePackModule.class);
    RubyClass standardErrorClass = runtime.getStandardError();
    RubyClass unpackErrorClass = msgpackModule.defineClassUnder("UnpackError", standardErrorClass, standardErrorClass.getAllocator());
    RubyClass underflowErrorClass = msgpackModule.defineClassUnder("UnderflowError", unpackErrorClass, unpackErrorClass.getAllocator());
    RubyClass extensionValueClass = msgpackModule.defineClassUnder("ExtensionValue", runtime.getObject(), new ExtensionValue.ExtensionValueAllocator());
    extensionValueClass.defineAnnotatedMethods(ExtensionValue.class);
    RubyClass unpackerClass = msgpackModule.defineClassUnder("Unpacker", runtime.getObject(), new Unpacker.UnpackerAllocator());
    unpackerClass.defineAnnotatedMethods(Unpacker.class);
    RubyClass bufferClass = msgpackModule.defineClassUnder("Buffer", runtime.getObject(), new Buffer.BufferAllocator());
    bufferClass.defineAnnotatedMethods(Buffer.class);
  }

  @JRubyModule(name = "MessagePack")
  public static class MessagePackModule {
    @JRubyMethod(module = true, required = 1, optional = 1, alias = {"dump"})
    public static IRubyObject pack(ThreadContext ctx, IRubyObject recv, IRubyObject[] args) {
      Encoder encoder = new Encoder(ctx.getRuntime());
      return encoder.encode(args[0]);
    }

    @JRubyMethod(module = true, required = 1, optional = 1, alias = {"load"})
    public static IRubyObject unpack(ThreadContext ctx, IRubyObject recv, IRubyObject[] args) {
      Decoder decoder = new Decoder(ctx.getRuntime(), args[0].asString().getBytes());
      return decoder.next();
    }
  }
}

@@ -304,53 +304,240 @@
 uby.
-anno.JRubyModule;%0Aimport org.jruby.anno.JRuby
+runtime.Block;%0Aimport org.jruby.runtime.Visibility;%0Aimport org.jruby.anno.JRubyModule;%0Aimport org.jruby.anno.JRubyMethod;%0Aimport org.jruby.internal.runtime.methods.CallConfiguration;%0Aimport org.jruby.internal.runtime.methods.Dynamic
 Meth
@@ -1329,32 +1329,207 @@
 onValue.class);%0A
+    RubyClass packerClass = msgpackModule.defineClassUnder(%22Packer%22, runtime.getObject(), new Packer.PackerAllocator());%0A    packerClass.defineAnnotatedMethods(Packer.class);%0A
     RubyClass un
@@ -1874,16 +1874,1157 @@
 class);%0A
+    installCoreExtensions(runtime);%0A  %7D%0A%0A  private void installCoreExtensions(Ruby runtime) %7B%0A    installCoreExtensions(%0A      runtime,%0A      runtime.getNilClass(),%0A      runtime.getTrueClass(),%0A      runtime.getFalseClass(),%0A      runtime.getFixnum(),%0A      runtime.getBignum(),%0A      runtime.getFloat(),%0A      runtime.getString(),%0A      runtime.getArray(),%0A      runtime.getHash(),%0A      runtime.getSymbol()%0A    );%0A  %7D%0A%0A  private void installCoreExtensions(Ruby runtime, RubyClass... classes) %7B%0A    for (RubyClass cls : classes) %7B%0A      cls.addMethod(%22to_msgpack%22, createToMsgpackMethod(runtime, cls));%0A    %7D%0A  %7D%0A%0A  private DynamicMethod createToMsgpackMethod(final Ruby runtime, RubyClass cls) %7B%0A    return new DynamicMethod(cls, Visibility.PUBLIC, CallConfiguration.FrameNoneScopeNone) %7B%0A      @Override%0A      public IRubyObject call(ThreadContext context, IRubyObject recv, RubyModule clazz, String name, IRubyObject%5B%5D args, Block block) %7B%0A        return MessagePackModule.pack(runtime.getCurrentContext(), null, new IRubyObject%5B%5D %7Brecv%7D);%0A      %7D%0A%0A      @Override%0A      public DynamicMethod dup() %7B%0A        return this;%0A      %7D%0A    %7D;%0A
   %7D%0A%0A  @

Add #to_msgpack to nil, true, false, String, etc.