File: Packer.java

package info (click to toggle)
ruby-msgpack 1.8.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 972 kB
  • sloc: ruby: 4,789; ansic: 4,309; java: 1,809; makefile: 4
file content (266 lines) | stat: -rw-r--r-- 9,118 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
package org.msgpack.jruby;


import org.jruby.Ruby;
import org.jruby.RubyModule;
import org.jruby.RubyClass;
import org.jruby.RubyObject;
import org.jruby.RubyArray;
import org.jruby.RubyHash;
import org.jruby.RubyIO;
import org.jruby.RubyNumeric;
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 org.jruby.util.TypeConverter;
import org.msgpack.jruby.ExtensionValue;

import org.jcodings.Encoding;

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

@JRubyClass(name="MessagePack::Packer")
public class Packer extends RubyObject {
  private static final long serialVersionUID = 8451274621499362492L;
  public transient ExtensionRegistry registry;
  private Buffer buffer;
  private transient Encoder encoder;
  private boolean hasSymbolExtType;
  private boolean hasBigintExtType;
  private transient Encoding binaryEncoding;

  public Packer(Ruby runtime, RubyClass type, ExtensionRegistry registry, boolean hasSymbolExtType, boolean hasBigintExtType) {
    super(runtime, type);
    this.registry = registry;
    this.hasSymbolExtType = hasSymbolExtType;
    this.hasBigintExtType = hasBigintExtType;
  }

  static class PackerAllocator implements ObjectAllocator {
    public IRubyObject allocate(Ruby runtime, RubyClass type) {
      return new Packer(runtime, type, null, false, false);
    }
  }

  @JRubyMethod(name = "initialize", optional = 2)
  public IRubyObject initialize(ThreadContext ctx, IRubyObject[] args) {
    boolean compatibilityMode = false;
    Ruby runtime = ctx.runtime;
    if (args.length > 0) {
      RubyHash options = null;
      if (args[args.length - 1] instanceof RubyHash) {
        options = (RubyHash) args[args.length - 1];
      } else if (args.length > 1 && args[args.length - 2] instanceof RubyHash) {
        options = (RubyHash) args[args.length - 2];
      }

      if (options != null) {
        IRubyObject mode = options.fastARef(runtime.newSymbol("compatibility_mode"));
        compatibilityMode = (mode != null) && mode.isTrue();
      }
    }
    if (registry == null) {
        // registry is null when allocate -> initialize
        // registry is already initialized (and somthing might be registered) when newPacker from Factory
        this.registry = new ExtensionRegistry();
    }
    this.encoder = new Encoder(runtime, this, compatibilityMode, registry, hasSymbolExtType, hasBigintExtType);
    this.buffer = new Buffer(runtime, runtime.getModule("MessagePack").getClass("Buffer"));
    this.buffer.initialize(ctx, args);
    this.binaryEncoding = runtime.getEncodingService().getAscii8bitEncoding();
    return this;
  }

  public static Packer newPacker(ThreadContext ctx, ExtensionRegistry extRegistry, boolean hasSymbolExtType, boolean hasBigintExtType, IRubyObject[] args) {
    Packer packer = new Packer(ctx.runtime, ctx.runtime.getModule("MessagePack").getClass("Packer"), extRegistry, hasSymbolExtType, hasBigintExtType);
    packer.initialize(ctx, args);
    return packer;
  }

  @JRubyMethod(name = "compatibility_mode?")
  public IRubyObject isCompatibilityMode(ThreadContext ctx) {
    return encoder.isCompatibilityMode() ? ctx.runtime.getTrue() : ctx.runtime.getFalse();
  }

  @JRubyMethod(name = "registered_types_internal", visibility = PRIVATE)
  public IRubyObject registeredTypesInternal(ThreadContext ctx) {
    return registry.toInternalPackerRegistry(ctx);
  }

  @JRubyMethod(name = "register_type_internal", required = 3, visibility = PRIVATE)
  public IRubyObject registerType(ThreadContext ctx, IRubyObject type, IRubyObject mod, IRubyObject proc) {
    testFrozen("MessagePack::Packer");

    Ruby runtime = ctx.runtime;

    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 (!(mod instanceof RubyModule)) {
      throw runtime.newArgumentError(String.format("expected Module/Class but found %s.", mod.getType().getName()));
    }
    RubyModule extModule = (RubyModule) mod;

    registry.put(extModule, (int) typeId, false, proc, null);

    if (extModule == runtime.getSymbol() && !proc.isNil()) {
      encoder.hasSymbolExtType = true;
    }

    return runtime.getNil();
  }

  @JRubyMethod(name = "write", alias = { "pack" })
  public IRubyObject write(ThreadContext ctx, IRubyObject obj) {
    buffer.write(ctx, encoder.encode(obj, this));
    return this;
  }

  @JRubyMethod(name = "write_float")
  public IRubyObject writeFloat(ThreadContext ctx, IRubyObject obj) {
    checkType(ctx, obj, org.jruby.RubyFloat.class);
    return write(ctx, obj);
  }

  @JRubyMethod(name = "write_array")
  public IRubyObject writeArray(ThreadContext ctx, IRubyObject obj) {
    checkType(ctx, obj, org.jruby.RubyArray.class);
    return write(ctx, obj);
  }

  @JRubyMethod(name = "write_string")
  public IRubyObject writeString(ThreadContext ctx, IRubyObject obj) {
    checkType(ctx, obj, org.jruby.RubyString.class);
    return write(ctx, obj);
  }

  @JRubyMethod(name = "write_bin")
  public IRubyObject writeBin(ThreadContext ctx, IRubyObject obj) {
    checkType(ctx, obj, org.jruby.RubyString.class);
    obj = ((org.jruby.RubyString) obj).encode(ctx, ctx.runtime.getEncodingService().getEncoding(binaryEncoding));
    return write(ctx, obj);
  }

  @JRubyMethod(name = "write_hash")
  public IRubyObject writeHash(ThreadContext ctx, IRubyObject obj) {
    checkType(ctx, obj, org.jruby.RubyHash.class);
    return write(ctx, obj);
  }

  @JRubyMethod(name = "write_symbol")
  public IRubyObject writeSymbol(ThreadContext ctx, IRubyObject obj) {
    checkType(ctx, obj, org.jruby.RubySymbol.class);
    return write(ctx, obj);
  }

  @JRubyMethod(name = "write_int")
  public IRubyObject writeInt(ThreadContext ctx, IRubyObject obj) {
    if (!(obj instanceof RubyFixnum)) {
      checkType(ctx, obj, org.jruby.RubyBignum.class);
    }
    return write(ctx, obj);
  }

  @JRubyMethod(name = "write_extension")
  public IRubyObject writeExtension(ThreadContext ctx, IRubyObject obj) {
    if (!(obj instanceof ExtensionValue)) {
      throw ctx.runtime.newTypeError("Expected extension");
    }
    return write(ctx, obj);
  }

  @JRubyMethod(name = "write_true")
  public IRubyObject writeTrue(ThreadContext ctx) {
    return write(ctx, ctx.runtime.getTrue());
  }

  @JRubyMethod(name = "write_false")
  public IRubyObject writeFalse(ThreadContext ctx) {
    return write(ctx, ctx.runtime.getFalse());
  }

  @JRubyMethod(name = "write_nil")
  public IRubyObject writeNil(ThreadContext ctx) {
    write(ctx, null);
    return this;
  }

  @JRubyMethod(name = "write_float32")
  public IRubyObject writeFloat32(ThreadContext ctx, IRubyObject numeric) {
    Ruby runtime = ctx.runtime;
    if (!(numeric instanceof RubyNumeric)) {
      throw runtime.newArgumentError("Expected numeric");
    }
    buffer.write(ctx, encoder.encodeFloat32((RubyNumeric) numeric));
    return this;
  }

  @JRubyMethod(name = "write_array_header")
  public IRubyObject writeArrayHeader(ThreadContext ctx, IRubyObject size) {
    int s = (int) size.convertToInteger().getLongValue();
    buffer.write(ctx, encoder.encodeArrayHeader(s));
    return this;
  }

  @JRubyMethod(name = "write_map_header")
  public IRubyObject writeMapHeader(ThreadContext ctx, IRubyObject size) {
    int s = (int) size.convertToInteger().getLongValue();
    buffer.write(ctx, encoder.encodeMapHeader(s));
    return this;
  }

  @JRubyMethod(name = "write_bin_header")
  public IRubyObject writeBinHeader(ThreadContext ctx, IRubyObject size) {
    int s = (int) size.convertToInteger().getLongValue();
    buffer.write(ctx, encoder.encodeBinHeader(s));
    return this;
  }

  @JRubyMethod(name = "full_pack")
  public IRubyObject fullPack(ThreadContext ctx) {
    if (buffer.hasIo()) {
      return null;
    }
    return toS(ctx);
  }

  @JRubyMethod(name = "to_s", alias = { "to_str" })
  public IRubyObject toS(ThreadContext ctx) {
    return buffer.toS(ctx);
  }

  @JRubyMethod(name = "buffer")
  public IRubyObject buffer(ThreadContext ctx) {
    return buffer;
  }

  @JRubyMethod(name = "flush")
  public IRubyObject flush(ThreadContext ctx) {
    return buffer.flush(ctx);
  }

  @JRubyMethod(name = "size")
  public IRubyObject size(ThreadContext ctx) {
    return buffer.size(ctx);
  }

  @JRubyMethod(name = "clear", alias = { "reset" })
  public IRubyObject clear(ThreadContext ctx) {
    return buffer.clear(ctx);
  }

  private void checkType(ThreadContext ctx, IRubyObject obj, Class<? extends IRubyObject> expectedType) {
    if (!expectedType.isInstance(obj)) {
      String expectedName = expectedType.getName().substring("org.jruby.Ruby".length());
      throw ctx.runtime.newTypeError(String.format("wrong argument type %s (expected %s)", obj.getMetaClass().toString(), expectedName));
    }
  }
}