1212import org .jruby .RubyClass ;
1313import org .jruby .RubyBignum ;
1414import org .jruby .RubyString ;
15+ import org .jruby .RubyArray ;
1516import org .jruby .RubyHash ;
1617import org .jruby .exceptions .RaiseException ;
1718import org .jruby .runtime .builtin .IRubyObject ;
@@ -29,33 +30,58 @@ public class Decoder implements Iterator<IRubyObject> {
2930 private final Encoding utf8Encoding ;
3031 private final RubyClass unpackErrorClass ;
3132 private final RubyClass underflowErrorClass ;
33+ private final RubyClass malformedFormatErrorClass ;
34+ private final RubyClass stackErrorClass ;
3235 private final RubyClass unexpectedTypeErrorClass ;
36+ private final RubyClass unknownExtTypeErrorClass ;
3337
38+ private ExtensionRegistry registry ;
3439 private ByteBuffer buffer ;
3540 private boolean symbolizeKeys ;
41+ private boolean allowUnknownExt ;
3642
3743 public Decoder (Ruby runtime ) {
38- this (runtime , new byte [] {}, 0 , 0 );
44+ this (runtime , null , new byte [] {}, 0 , 0 , false , false );
45+ }
46+
47+ public Decoder (Ruby runtime , ExtensionRegistry registry ) {
48+ this (runtime , registry , new byte [] {}, 0 , 0 , false , false );
3949 }
4050
4151 public Decoder (Ruby runtime , byte [] bytes ) {
42- this (runtime , bytes , 0 , bytes .length );
52+ this (runtime , null , bytes , 0 , bytes .length , false , false );
53+ }
54+
55+ public Decoder (Ruby runtime , ExtensionRegistry registry , byte [] bytes ) {
56+ this (runtime , registry , bytes , 0 , bytes .length , false , false );
57+ }
58+
59+ public Decoder (Ruby runtime , ExtensionRegistry registry , byte [] bytes , boolean symbolizeKeys , boolean allowUnknownExt ) {
60+ this (runtime , registry , bytes , 0 , bytes .length , symbolizeKeys , allowUnknownExt );
61+ }
62+
63+ public Decoder (Ruby runtime , ExtensionRegistry registry , byte [] bytes , int offset , int length ) {
64+ this (runtime , registry , bytes , offset , length , false , false );
4365 }
4466
45- public Decoder (Ruby runtime , byte [] bytes , int offset , int length ) {
67+ public Decoder (Ruby runtime , ExtensionRegistry registry , byte [] bytes , int offset , int length , boolean symbolizeKeys , boolean allowUnknownExt ) {
4668 this .runtime = runtime ;
69+ this .registry = registry ;
70+ this .symbolizeKeys = symbolizeKeys ;
71+ this .allowUnknownExt = allowUnknownExt ;
4772 this .binaryEncoding = runtime .getEncodingService ().getAscii8bitEncoding ();
4873 this .utf8Encoding = UTF8Encoding .INSTANCE ;
4974 this .unpackErrorClass = runtime .getModule ("MessagePack" ).getClass ("UnpackError" );
5075 this .underflowErrorClass = runtime .getModule ("MessagePack" ).getClass ("UnderflowError" );
76+ this .malformedFormatErrorClass = runtime .getModule ("MessagePack" ).getClass ("MalformedFormatError" );
77+ this .stackErrorClass = runtime .getModule ("MessagePack" ).getClass ("StackError" );
5178 this .unexpectedTypeErrorClass = runtime .getModule ("MessagePack" ).getClass ("UnexpectedTypeError" );
79+ this .unknownExtTypeErrorClass = runtime .getModule ("MessagePack" ).getClass ("UnknownExtTypeError" );
80+ this .symbolizeKeys = symbolizeKeys ;
81+ this .allowUnknownExt = allowUnknownExt ;
5282 feed (bytes , offset , length );
5383 }
5484
55- public void symbolizeKeys (boolean symbolize ) {
56- this .symbolizeKeys = symbolize ;
57- }
58-
5985 public void feed (byte [] bytes ) {
6086 feed (bytes , 0 , bytes .length );
6187 }
@@ -73,7 +99,7 @@ public void feed(byte[] bytes, int offset, int length) {
7399 }
74100
75101 public void reset () {
76- buffer . rewind () ;
102+ buffer = null ;
77103 }
78104
79105 public int offset () {
@@ -118,7 +144,20 @@ private IRubyObject consumeHash(int size) {
118144 private IRubyObject consumeExtension (int size ) {
119145 int type = buffer .get ();
120146 byte [] payload = readBytes (size );
121- return ExtensionValue .newExtensionValue (runtime , type , payload );
147+
148+ if (registry != null ) {
149+ IRubyObject proc = registry .lookupUnpackerByTypeId (type );
150+ if (proc != null ) {
151+ ByteList byteList = new ByteList (payload , runtime .getEncodingService ().getAscii8bitEncoding ());
152+ return proc .callMethod (runtime .getCurrentContext (), "call" , runtime .newString (byteList ));
153+ }
154+ }
155+
156+ if (this .allowUnknownExt ) {
157+ return ExtensionValue .newExtensionValue (runtime , type , payload );
158+ }
159+
160+ throw runtime .newRaiseException (unknownExtTypeErrorClass , "unexpected extension type" );
122161 }
123162
124163 private byte [] readBytes (int size ) {
@@ -142,11 +181,11 @@ public IRubyObject read_array_header() {
142181 try {
143182 byte b = buffer .get ();
144183 if ((b & 0xf0 ) == 0x90 ) {
145- return runtime .newFixnum (b & 0x0f );
184+ return runtime .newFixnum (b & 0x0f );
146185 } else if (b == ARY16 ) {
147- return runtime .newFixnum (buffer .getShort () & 0xffff );
186+ return runtime .newFixnum (buffer .getShort () & 0xffff );
148187 } else if (b == ARY32 ) {
149- return runtime .newFixnum (buffer .getInt ());
188+ return runtime .newFixnum (buffer .getInt ());
150189 }
151190 throw runtime .newRaiseException (unexpectedTypeErrorClass , "unexpected type" );
152191 } catch (RaiseException re ) {
@@ -163,11 +202,11 @@ public IRubyObject read_map_header() {
163202 try {
164203 byte b = buffer .get ();
165204 if ((b & 0xf0 ) == 0x80 ) {
166- return runtime .newFixnum (b & 0x0f );
205+ return runtime .newFixnum (b & 0x0f );
167206 } else if (b == MAP16 ) {
168- return runtime .newFixnum (buffer .getShort () & 0xffff );
207+ return runtime .newFixnum (buffer .getShort () & 0xffff );
169208 } else if (b == MAP32 ) {
170- return runtime .newFixnum (buffer .getInt ());
209+ return runtime .newFixnum (buffer .getInt ());
171210 }
172211 throw runtime .newRaiseException (unexpectedTypeErrorClass , "unexpected type" );
173212 } catch (RaiseException re ) {
@@ -233,7 +272,7 @@ public IRubyObject next() {
233272 default : return runtime .newFixnum (b );
234273 }
235274 buffer .position (position );
236- throw runtime .newRaiseException (unpackErrorClass , "Illegal byte sequence" );
275+ throw runtime .newRaiseException (malformedFormatErrorClass , "Illegal byte sequence" );
237276 } catch (RaiseException re ) {
238277 buffer .position (position );
239278 throw re ;
0 commit comments