-
Notifications
You must be signed in to change notification settings - Fork 121
add full spec ext type support to JRuby implementation #91
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
40 commits
Select commit
Hold shift + click to select a range
f55e1d1
Adding full spec ext type implementation for JRuby
tagomoris edd345b
add TODOs to remove unused code
tagomoris 7af6059
cross-compile utility only for CRuby runtime
tagomoris 76ba902
Fix bug to do invalid cast before check whether value is of int corre…
tagomoris b498368
add registered_types_internal and register_type for jruby implementation
tagomoris 8aec89a
Fix to check included classes to fetch how to serialize
tagomoris 1a2edf6
fix to check compatibility_mode option is missing
tagomoris fdc71d4
add missing aliases as same with cruby implementation
tagomoris ca3b4a0
add missing aliases and exceptions
tagomoris 630a9d8
WIP: merging crubyjruby specs
tagomoris 130be0c
ignore vim swp files
tagomoris f3c3159
improve compatibility: raise EOFError for reading before feeding
tagomoris f580c47
improve compatibility: Unpacker#feed_each without blocks should retur…
tagomoris b0203f9
improve compatibility: reset should just clear internal buffer
tagomoris 20c42e5
it highly depends on CRuby implementation internals
tagomoris 5e0ce6d
correct code for current dependent Rspec
tagomoris 534b705
separate jruby-specific specs for unpacker into jruby/ directory
tagomoris fe0f5b9
specs merged for both of CRuby and JRuby
tagomoris a0e72d1
remove .swp file which added in mistake
tagomoris 0ca45a4
remove skips for java implementations (missed to be removed)
tagomoris 629cc50
fix to raise same exception with c impl. for unknown extension types
tagomoris 2441df7
RubyHash#fastARef returns null instead of nil if specified key is mis…
tagomoris b85c3ba
array size must be 2 not 0
tagomoris 6977b42
include_p is only for included Modules: check ancestors list instead
tagomoris 1c3e205
fix code styles and remove useless comments/unused functions
tagomoris e04ee3b
remove additional this. and comments
tagomoris 32a3686
use long descriptive name for class
tagomoris 6dcc117
add getter for Packer/Unpacker configuration (mainly for tests)
tagomoris f763ed3
Remove setters from Decoder
iconara 48f9ab5
Remove setter from Encoder
iconara ac21a80
Remove comments
iconara 230b313
Replace a comment with a method
iconara cc5a019
Simplify array construction in Packer.ExtensionRegistry
iconara 18e070e
Remove an unnecessary comment
iconara d1d1f0e
fix symbolizeKeys/allowUnknownExt for Decoder as constructor arguments
tagomoris 1e9ba40
Extract Packer.ExtensionRegistry to its own class and clean up the in…
iconara 9b76228
Replace Unpacker.ExtensionRegistry with ExtensionRegistry
iconara be0018c
Merge branch 'ext-type-jruby' into ext-type-jruby-theo
tagomoris 6ee1b67
ExtensionRegistry must return typeId for Packer and class for Unpacker
tagomoris 654de1b
List of registered ext types must be listed by typeId, not class
tagomoris File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,6 +11,7 @@ Gemfile* | |
| pkg | ||
| test/debug.log | ||
| *~ | ||
| *.swp | ||
| /rdoc | ||
| tmp | ||
| .classpath | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,159 @@ | ||
| package org.msgpack.jruby; | ||
|
|
||
| import org.jruby.Ruby; | ||
| import org.jruby.RubyHash; | ||
| import org.jruby.RubyArray; | ||
| import org.jruby.RubyClass; | ||
| import org.jruby.RubyFixnum; | ||
| import org.jruby.runtime.ThreadContext; | ||
| import org.jruby.runtime.builtin.IRubyObject; | ||
|
|
||
| import java.util.Map; | ||
| import java.util.HashMap; | ||
|
|
||
| public class ExtensionRegistry { | ||
| private final Map<RubyClass, ExtensionEntry> extensionsByClass; | ||
| private final Map<RubyClass, ExtensionEntry> extensionsByAncestor; | ||
| private final ExtensionEntry[] extensionsByTypeId; | ||
|
|
||
| public ExtensionRegistry() { | ||
| this(new HashMap<RubyClass, ExtensionEntry>()); | ||
| } | ||
|
|
||
| private ExtensionRegistry(Map<RubyClass, ExtensionEntry> extensionsByClass) { | ||
| this.extensionsByClass = new HashMap<RubyClass, ExtensionEntry>(extensionsByClass); | ||
| this.extensionsByAncestor = new HashMap<RubyClass, ExtensionEntry>(); | ||
| this.extensionsByTypeId = new ExtensionEntry[256]; | ||
| for (ExtensionEntry entry : extensionsByClass.values()) { | ||
| if (entry.hasUnpacker()) { | ||
| extensionsByTypeId[entry.getTypeId() + 128] = entry; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| public ExtensionRegistry dup() { | ||
| return new ExtensionRegistry(extensionsByClass); | ||
| } | ||
|
|
||
| public IRubyObject toInternalPackerRegistry(ThreadContext ctx) { | ||
| RubyHash hash = RubyHash.newHash(ctx.getRuntime()); | ||
| for (RubyClass extensionClass : extensionsByClass.keySet()) { | ||
| ExtensionEntry entry = extensionsByClass.get(extensionClass); | ||
| if (entry.hasPacker()) { | ||
| hash.put(extensionClass, entry.toPackerTuple(ctx)); | ||
| } | ||
| } | ||
| return hash; | ||
| } | ||
|
|
||
| public IRubyObject toInternalUnpackerRegistry(ThreadContext ctx) { | ||
| RubyHash hash = RubyHash.newHash(ctx.getRuntime()); | ||
| for (int typeIdIndex = 0 ; typeIdIndex < 256 ; typeIdIndex++) { | ||
| ExtensionEntry entry = extensionsByTypeId[typeIdIndex]; | ||
| if (entry != null && entry.hasUnpacker()) { | ||
| IRubyObject typeId = RubyFixnum.newFixnum(ctx.getRuntime(), typeIdIndex - 128); | ||
| hash.put(typeId, entry.toUnpackerTuple(ctx)); | ||
| } | ||
| } | ||
| return hash; | ||
| } | ||
|
|
||
| public void put(RubyClass cls, int typeId, IRubyObject packerProc, IRubyObject packerArg, IRubyObject unpackerProc, IRubyObject unpackerArg) { | ||
| ExtensionEntry entry = new ExtensionEntry(cls, typeId, packerProc, packerArg, unpackerProc, unpackerArg); | ||
| extensionsByClass.put(cls, entry); | ||
| extensionsByTypeId[typeId + 128] = entry; | ||
| extensionsByAncestor.clear(); | ||
| } | ||
|
|
||
| public IRubyObject lookupUnpackerByTypeId(int typeId) { | ||
| ExtensionEntry e = extensionsByTypeId[typeId + 128]; | ||
| if (e != null && e.hasUnpacker()) { | ||
| return e.getUnpackerProc(); | ||
| } else { | ||
| return null; | ||
| } | ||
| } | ||
|
|
||
| public IRubyObject[] lookupPackerByClass(RubyClass cls) { | ||
| ExtensionEntry e = extensionsByClass.get(cls); | ||
| if (e == null) { | ||
| e = extensionsByAncestor.get(cls); | ||
| } | ||
| if (e == null) { | ||
| e = findEntryByClassOrAncestor(cls); | ||
| if (e != null) { | ||
| extensionsByAncestor.put(e.getExtensionClass(), e); | ||
| } | ||
| } | ||
| if (e != null && e.hasPacker()) { | ||
| return e.toPackerProcTypeIdPair(cls.getRuntime().getCurrentContext()); | ||
| } else { | ||
| return null; | ||
| } | ||
| } | ||
|
|
||
| private ExtensionEntry findEntryByClassOrAncestor(final RubyClass cls) { | ||
| ThreadContext ctx = cls.getRuntime().getCurrentContext(); | ||
| for (RubyClass extensionClass : extensionsByClass.keySet()) { | ||
| RubyArray ancestors = (RubyArray) cls.callMethod(ctx, "ancestors"); | ||
| if (ancestors.callMethod(ctx, "include?", extensionClass).isTrue()) { | ||
| return extensionsByClass.get(extensionClass); | ||
| } | ||
| } | ||
| return null; | ||
| } | ||
|
|
||
| private static class ExtensionEntry { | ||
| private final RubyClass cls; | ||
| private final int typeId; | ||
| private final IRubyObject packerProc; | ||
| private final IRubyObject packerArg; | ||
| private final IRubyObject unpackerProc; | ||
| private final IRubyObject unpackerArg; | ||
|
|
||
| public ExtensionEntry(RubyClass cls, int typeId, IRubyObject packerProc, IRubyObject packerArg, IRubyObject unpackerProc, IRubyObject unpackerArg) { | ||
| this.cls = cls; | ||
| this.typeId = typeId; | ||
| this.packerProc = packerProc; | ||
| this.packerArg = packerArg; | ||
| this.unpackerProc = unpackerProc; | ||
| this.unpackerArg = unpackerArg; | ||
| } | ||
|
|
||
| public RubyClass getExtensionClass() { | ||
| return cls; | ||
| } | ||
|
|
||
| public int getTypeId() { | ||
| return typeId; | ||
| } | ||
|
|
||
| public boolean hasPacker() { | ||
| return packerProc != null; | ||
| } | ||
|
|
||
| public boolean hasUnpacker() { | ||
| return unpackerProc != null; | ||
| } | ||
|
|
||
| public IRubyObject getPackerProc() { | ||
| return packerProc; | ||
| } | ||
|
|
||
| public IRubyObject getUnpackerProc() { | ||
| return unpackerProc; | ||
| } | ||
|
|
||
| public RubyArray toPackerTuple(ThreadContext ctx) { | ||
| return RubyArray.newArray(ctx.getRuntime(), new IRubyObject[] {RubyFixnum.newFixnum(ctx.getRuntime(), typeId), packerProc, packerArg}); | ||
| } | ||
|
|
||
| public RubyArray toUnpackerTuple(ThreadContext ctx) { | ||
| return RubyArray.newArray(ctx.getRuntime(), new IRubyObject[] {cls, unpackerProc, unpackerArg}); | ||
| } | ||
|
|
||
| public IRubyObject[] toPackerProcTypeIdPair(ThreadContext ctx) { | ||
| return new IRubyObject[] {packerProc, RubyFixnum.newFixnum(ctx.getRuntime(), typeId)}; | ||
| } | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be a constructor argument.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It can't be, because registries will be overwritten when initialized from factories.
https://github.com/msgpack/msgpack-ruby/blob/ext-type-jruby/ext/java/org/msgpack/jruby/Packer.java#L114