asciipack 0.1.3 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,299 @@
1
+ #include "unpacker.h"
2
+
3
+ VALUE cAsciiPack_Unpacker;
4
+
5
+ static VALUE Unpacker_read(unpacker_t* ptr);
6
+
7
+ static void
8
+ unpacker_mark(unpacker_t* ptr)
9
+ {
10
+ }
11
+
12
+ static VALUE
13
+ Unpacker_alloc(VALUE klass)
14
+ {
15
+ unpacker_t *ptr = ALLOC(unpacker_t);
16
+ return Data_Wrap_Struct(klass, unpacker_mark, -1, ptr);
17
+ }
18
+
19
+ static VALUE
20
+ Unpacker_init(VALUE self, VALUE obj, int argc, VALUE *argv, VALUE size)
21
+ {
22
+ UNPACKER(self, ptr);
23
+
24
+ if (!ptr) {
25
+ rb_raise(rb_eArgError, "unallocated unpacker");
26
+ }
27
+
28
+ ptr->buffer = RSTRING_PTR(obj);
29
+ ptr->ch = ptr->buffer;
30
+
31
+ return self;
32
+ }
33
+
34
+ static VALUE
35
+ Unpacker_initialize(int argc, VALUE *argv, VALUE self)
36
+ {
37
+ VALUE obj = *argv++;
38
+ VALUE size = Qnil;
39
+ return Unpacker_init(self, obj, argc, argv, size);
40
+ }
41
+
42
+ static unsigned short
43
+ to_i16 (char ch)
44
+ {
45
+ unsigned short ret = 0;
46
+ if ('0' <= ch && ch <= '9') {
47
+ ret += ch - '0';
48
+ } else if ('a' <= ch && ch <= 'f') {
49
+ ret += ch - 'a' + 10;
50
+ }
51
+ return ret;
52
+ }
53
+
54
+ static uint64_t
55
+ to_i16all (unpacker_t* ptr, int len)
56
+ {
57
+ uint64_t ret = 0;
58
+ while (len--) {
59
+ ret += to_i16(*ptr->ch);
60
+ ptr->ch++;
61
+ if (len != 0) ret = ret << 4;
62
+ }
63
+ return ret;
64
+ }
65
+
66
+ static uint64_t
67
+ Unpacker_int (unpacker_t* ptr, size_t len)
68
+ {
69
+ size_t n = len;
70
+ char* head = ptr->ch;
71
+ uint64_t base = 1;
72
+ uint64_t ret = to_i16all(ptr, len);
73
+
74
+ if ('8' <= *head) {
75
+ ret -= (base << (n * 4));
76
+ }
77
+ return ret;
78
+ }
79
+
80
+ static uint64_t
81
+ Unpacker_uint (unpacker_t* ptr, size_t len)
82
+ {
83
+ return to_i16all(ptr, len);
84
+ }
85
+
86
+ static double
87
+ Unpacker_float (unpacker_t* ptr, size_t len)
88
+ {
89
+ uint64_t ret = to_i16all(ptr, len);
90
+ /* for convert unsigned long <-> float */
91
+ union {
92
+ unsigned long u;
93
+ double f64;
94
+ } converter = {ret};
95
+ return converter.f64;
96
+ }
97
+
98
+ static VALUE
99
+ Unpacker_str (unpacker_t* ptr, size_t len)
100
+ {
101
+ char* head = ptr->ch;
102
+
103
+ VALUE str = rb_str_new(head, len);
104
+ rb_funcall(str, rb_intern("force_encoding"), 1, rb_str_new2("utf-8"));
105
+ return str;
106
+ }
107
+
108
+ static VALUE
109
+ Unpacker_map (unpacker_t* ptr, size_t len)
110
+ {
111
+ VALUE map = rb_hash_new();
112
+ VALUE key, value;
113
+ while (len--) {
114
+ key = Unpacker_read(ptr);
115
+ value = Unpacker_read(ptr);
116
+ rb_hash_aset(map, key, value);
117
+ }
118
+ return map;
119
+ }
120
+
121
+ static VALUE
122
+ Unpacker_array (unpacker_t* ptr, size_t len)
123
+ {
124
+ VALUE array = rb_ary_new2(len);
125
+ while (len--) {
126
+ rb_ary_push(array, Unpacker_read(ptr));
127
+ }
128
+ return array;
129
+ }
130
+
131
+ static VALUE
132
+ Unpacker_read (unpacker_t* ptr)
133
+ {
134
+ uint64_t num;
135
+
136
+ ptr->ch++;
137
+
138
+ switch (*(ptr->ch - 1)) {
139
+ case 'a': // int 4
140
+ num = Unpacker_int(ptr, 1);
141
+ return INT2FIX(num);
142
+
143
+ case 'b': // int 8
144
+ num = Unpacker_int(ptr, 2);
145
+ return INT2FIX(num);
146
+
147
+ case 'c': // int 16
148
+ num = Unpacker_int(ptr, 4);
149
+ return INT2FIX(num);
150
+
151
+ case 'd': // int 32
152
+ num = Unpacker_int(ptr, 8);
153
+ return LONG2NUM(num);
154
+
155
+ case 'e': // int 64
156
+ num = Unpacker_int(ptr, 16);
157
+ return rb_ll2inum(num);
158
+
159
+ case 'g': // uint 8
160
+ num = Unpacker_uint(ptr, 2);
161
+ return INT2FIX(num);
162
+
163
+ case 'h': // uint 16
164
+ num = Unpacker_uint(ptr, 4);
165
+ return INT2FIX(num);
166
+
167
+ case 'i': // uint 32
168
+ num = Unpacker_uint(ptr, 8);
169
+ return LONG2NUM(num);
170
+
171
+ case 'j': // uint 64
172
+ num = Unpacker_uint(ptr, 16);
173
+ return rb_ull2inum(num);
174
+
175
+ case 'k': // float 32
176
+ return rb_float_new(Unpacker_float(ptr, 8));
177
+
178
+ case 'l': // float 64
179
+ return rb_float_new(Unpacker_float(ptr, 16));
180
+
181
+ case 'n': // str 8
182
+ num = Unpacker_uint(ptr, 2);
183
+ return Unpacker_str(ptr, num);
184
+
185
+ case 'o': // str 16
186
+ num = Unpacker_uint(ptr, 4);
187
+ return Unpacker_str(ptr, num);
188
+
189
+ case 'p': // str 32
190
+ num = Unpacker_uint(ptr, 8);
191
+ return Unpacker_str(ptr, num);
192
+
193
+ case 'r': // map 4
194
+ num = Unpacker_uint(ptr, 1);
195
+ return Unpacker_map(ptr, num);
196
+
197
+ case 's': // map 8
198
+ num = Unpacker_uint(ptr, 2);
199
+ return Unpacker_map(ptr, num);
200
+
201
+ case 't': // map16
202
+ num = Unpacker_uint(ptr, 4);
203
+ return Unpacker_map(ptr, num);
204
+
205
+ case 'u': // map 32
206
+ num = Unpacker_uint(ptr, 8);
207
+ return Unpacker_map(ptr, num);
208
+
209
+ case 'v': // array 4
210
+ num = Unpacker_uint(ptr, 1);
211
+ return Unpacker_array(ptr, num);
212
+
213
+ case 'w': // array 8
214
+ num = Unpacker_uint(ptr, 2);
215
+ return Unpacker_array(ptr, num);
216
+
217
+ case 'x': // array 16
218
+ num = Unpacker_uint(ptr, 4);
219
+ return Unpacker_array(ptr, num);
220
+
221
+ case 'y': // array 32
222
+ num = Unpacker_uint(ptr, 8);
223
+ return Unpacker_array(ptr, num);
224
+
225
+ // positive fixint
226
+ case '0': return INT2FIX(0);
227
+ case '1': return INT2FIX(1);
228
+ case '2': return INT2FIX(2);
229
+ case '3': return INT2FIX(3);
230
+ case '4': return INT2FIX(4);
231
+ case '5': return INT2FIX(5);
232
+ case '6': return INT2FIX(6);
233
+ case '7': return INT2FIX(7);
234
+ case '8': return INT2FIX(8);
235
+ case '9': return INT2FIX(9);
236
+ case 'A': return INT2FIX(10);
237
+ case 'B': return INT2FIX(11);
238
+ case 'C': return INT2FIX(12);
239
+ case 'D': return INT2FIX(13);
240
+ case 'E': return INT2FIX(14);
241
+ case 'F': return INT2FIX(15);
242
+
243
+ // fixstr
244
+ case 'G':
245
+ return rb_str_new2("");
246
+ case 'H':
247
+ case 'I':
248
+ case 'J':
249
+ case 'K':
250
+ case 'L':
251
+ case 'M':
252
+ case 'N':
253
+ case 'O':
254
+ case 'P':
255
+ case 'Q':
256
+ case 'R':
257
+ case 'S':
258
+ case 'T':
259
+ case 'U':
260
+ case 'V':
261
+ num = *(ptr->ch - 1) - 'G';
262
+ return Unpacker_str(ptr, num);
263
+
264
+ // others
265
+ case 'W': return Qnil;
266
+ case 'X': return Qfalse;
267
+ case 'Y': return Qtrue;
268
+ }
269
+
270
+ rb_raise(rb_eArgError, "undefined type:%c", *(ptr->ch));
271
+ return Qnil;
272
+ }
273
+
274
+ static VALUE
275
+ Unpacker_unpack (VALUE self)
276
+ {
277
+ UNPACKER(self, ptr);
278
+ return Unpacker_read(ptr);
279
+ }
280
+
281
+ static VALUE
282
+ AsciiPack_unpack (int argc, VALUE *argv, VALUE self)
283
+ {
284
+ VALUE unpacker = rb_funcall(cAsciiPack_Unpacker, rb_intern("new"), 1, argv[0]);
285
+ return rb_funcall(unpacker, rb_intern("unpack"), 0);
286
+ }
287
+
288
+ void
289
+ AsciiPack_Unpacker_init(VALUE mAsciiPack)
290
+ {
291
+ cAsciiPack_Unpacker = rb_define_class_under(mAsciiPack, "Unpacker", rb_cObject);
292
+
293
+ rb_define_alloc_func(cAsciiPack_Unpacker, Unpacker_alloc);
294
+
295
+ rb_define_method(cAsciiPack_Unpacker, "initialize", Unpacker_initialize, -1);
296
+ rb_define_method(cAsciiPack_Unpacker, "unpack", Unpacker_unpack, 0);
297
+
298
+ rb_define_module_function(mAsciiPack, "unpack", AsciiPack_unpack, -1);
299
+ }
@@ -0,0 +1,25 @@
1
+ #ifndef UNPACKER_H
2
+ # define UNPACKER_H
3
+
4
+ #include <stdlib.h>
5
+
6
+ struct unpacker {
7
+ char* buffer;
8
+ char* ch;
9
+ };
10
+ typedef struct unpacker unpacker_t;
11
+
12
+ #define UNPACKER(from, name) \
13
+ unpacker_t* name; \
14
+ Data_Get_Struct(from, unpacker_t, name); \
15
+ if (name == NULL) { \
16
+ rb_raise(rb_eArgError, "NULL found for " # name " when shouldn't be.'"); \
17
+ }
18
+
19
+ #include "ruby.h"
20
+
21
+ extern VALUE cAsciiPack_Unpacker;
22
+ void AsciiPack_Unpacker_init(VALUE mAsciiPack);
23
+
24
+ #endif /* ifndef UNPACKER_H */
25
+
@@ -1,3 +1,3 @@
1
1
  module AsciiPack
2
- VERSION = "0.1.3"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/asciipack.rb CHANGED
@@ -1,3 +1,3 @@
1
+ here = File.expand_path(File.dirname(__FILE__))
2
+ require File.join(here, 'asciipack', 'asciipack')
1
3
  require "asciipack/version"
2
- require 'asciipack/packer.rb'
3
- require 'asciipack/unpacker.rb'
data/spec/bench.rb CHANGED
@@ -7,51 +7,70 @@ require 'asciipack'
7
7
  require 'json'
8
8
  require 'msgpack'
9
9
 
10
- def json_asciipack(name, obj)
10
+ def count
11
+ 10000
12
+ end
13
+
14
+ def reports (obj)
11
15
  obj = [obj]
12
16
  json = obj.to_json
13
17
  ap = AsciiPack.pack obj
14
18
  ms = Marshal.dump obj
15
19
  msg = MessagePack.pack obj
16
20
 
17
- p '[' + name + ']'
18
- bench "AsciiPack.pack" do AsciiPack.pack obj end
19
- bench "AsciiPack.unpack" do AsciiPack.unpack ap end
20
- bench "JSON.generate" do obj.to_json end
21
- bench "JSON.parse" do JSON.parse json end
22
- bench "Marshal.dump" do Marshal.dump obj end
23
- bench "Marshal.load" do Marshal.load ms end
24
- bench "MessagePack.pack" do MessagePack.pack obj end
25
- bench "MessagePack.unpack" do MessagePack.unpack msg end
26
- p({
27
- :ap => ap.length,
28
- :json => json.length,
29
- :marshal => ms.length,
30
- :msgpack => msg.length
31
- })
21
+ {
22
+ "AsciiPack.pack" => lambda { AsciiPack.pack obj },
23
+ "AsciiPack.unpack" => lambda { AsciiPack.unpack ap },
24
+ "MessagePack.pack" => lambda { MessagePack.pack obj },
25
+ "MessagePack.unpack" => lambda { MessagePack.unpack msg },
26
+ "JSON.generate" => lambda { obj.to_json },
27
+ "JSON.parse" => lambda { JSON.parse json },
28
+ "Marshal.dump" => lambda { Marshal.dump obj },
29
+ "Marshal.load" => lambda { Marshal.load ms },
30
+ }
32
31
  end
33
32
 
34
- def bench(name)
35
- t = Time.now
36
- 100000.times {
37
- yield
33
+ def json_asciipack(name, obj)
34
+ print("|" + name + "|")
35
+
36
+ results = []
37
+ reports(obj).each { |_, func|
38
+ t = Time.now
39
+ count.times {
40
+ func.call
41
+ }
42
+ results << "%.1f" % ((Time.now - t) * 1000)
38
43
  }
39
- p name + ': ' + (Time.now - t).to_s + 's'
44
+ puts results.join("|") + "|"
40
45
  end
41
46
 
47
+ puts("|object|" + reports(0).keys.join("|") + "|")
48
+ puts("|---|" + reports(0).keys.map{"---"}.join("|") + "|")
49
+
50
+ map16 = {}
51
+ a = '@'
52
+ 0x100.times {|i| map16[i.to_s] = 0 }
53
+
42
54
  tt = Time.now
43
55
  {
44
56
  "positive fixint" => 0,
45
- "uint 4" => 16,
57
+ "uint 64" => 0xffffffffffffffff,
46
58
  "int 4" => -1,
47
- "fixstr" => "",
48
- "str 8" => '0123456789abcdef',
59
+ "int 64" => -0x8000000000000000,
49
60
  "float 64" => 1/3,
61
+ "fixstr" => "a",
62
+ "str 32" => 'a' * 0x10000,
50
63
  "map 4" => {},
64
+ "map 16" => map16,
51
65
  "array 4" => [],
66
+ "array 16" => Array.new(0x100,0),
52
67
  "nil" => nil,
53
68
  }.each { |key, value|
54
69
  json_asciipack key, value
55
70
  }
56
71
 
57
- p 'total: ' + (Time.now - tt).to_s + 's'
72
+ puts "\n"
73
+ puts "count:#{count}"
74
+ puts "unit:/ms"
75
+ puts 'total:' + (Time.now - tt).to_s + 's'
76
+
data/spec/format_spec.rb CHANGED
@@ -64,39 +64,41 @@ describe AsciiPack do
64
64
  format 1.0, T.float64, 17
65
65
  format 0.1, T.float64, 17
66
66
  format -0.1, T.float64, 17
67
- expect(AsciiPack.pack(-0.1)).to eq(T.float64 + 'bfb999999999999a')
68
- expect(AsciiPack.pack(1.0)).to eq(T.float64 + '3ff0000000000000')
69
- expect(AsciiPack.pack(1.0000000000000002)).to eq(T.float64 + '3ff0000000000001')
70
- expect(AsciiPack.pack(1.0000000000000004)).to eq(T.float64 + '3ff0000000000002')
71
- expect(AsciiPack.pack(1/3.0)).to eq(T.float64 + '3fd5555555555555')
72
- expect(AsciiPack.pack(Float::NAN)).to eq(T.float64 + '7fffffffffffffff')
73
- expect(AsciiPack.pack(1 / 0.0)).to eq(T.float64 + '7ff0000000000000')
74
- expect(AsciiPack.pack(-1 / 0.0)).to eq(T.float64 + 'fff0000000000000')
67
+ check_each_other(-0.1, T.float64 + 'bfb999999999999a')
68
+ check_each_other(1.0, T.float64 + '3ff0000000000000')
69
+ check_each_other(1.0000000000000002, T.float64 + '3ff0000000000001')
70
+ check_each_other(1.0000000000000004, T.float64 + '3ff0000000000002')
71
+ check_each_other(1/3.0, T.float64 + '3fd5555555555555')
72
+ expect(AsciiPack.pack(Float::NAN)).to eq(T.float64 + '7ff8000000000000')
73
+ check_each_other(1 / 0.0, T.float64 + '7ff0000000000000')
74
+ check_each_other(-1 / 0.0, T.float64 + 'fff0000000000000')
75
75
  end
76
76
 
77
- it "fixbin" do
78
- format "", T.fixbin_0, 1
79
- format " ", T.fixbin_1, 2
80
- format "あ", T.fixbin_1, 2
81
- format "漢字", T.fixbin_2, 3
82
- format " " * 0xe, T.fixbin_E, 15
83
- format " " * 0xf, T.fixbin_F, 16
77
+ it "fixstr" do
78
+ format "", T.fixstr_0, 1
79
+ format " ", T.fixstr_1, 2
80
+ format "あ", T.fixstr_3, 4
81
+ format "漢字", T.fixstr_6, 7
82
+ format " " * 0xe, T.fixstr_E, 15
83
+ format " " * 0xf, T.fixstr_F, 16
84
84
  end
85
85
 
86
- it "bin 8" do
87
- format "a" * 0x10, T.bin8, 3 + 0x10
88
- format "a" * 0xff, T.bin8, 3 + 0xff
86
+ it "str 8" do
87
+ format "a" * 0x10, T.str8, 3 + 0x10
88
+ format "a" * 0xff, T.str8, 3 + 0xff
89
89
  end
90
90
 
91
- it "bin 16" do
92
- format "a" * 0x100, T.bin16, 5 + 0x100
93
- format "a" * 0xffff, T.bin16, 5 + 0xffff
91
+ it "str 16" do
92
+ 100.times {
93
+ format "a" * 0x100, T.str16, 5 + 0x100
94
+ format "a" * 0xffff, T.str16, 5 + 0xffff
95
+ }
94
96
  end
95
97
 
96
- it "bin 32" do
97
- format "a" * 0x10000, T.bin32, 9 + 0x10000
98
+ it "str 32" do
99
+ format "a" * 0x10000, T.str32, 9 + 0x10000
98
100
  # FIXME too late
99
- # format "a" * 0xffffffff, T.bin32, 9 + 0xffffffff
101
+ # format "a" * 0xffffffff, T.str32, 9 + 0xffffffff
100
102
  end
101
103
 
102
104
  it "map 4" do
@@ -141,6 +143,15 @@ describe AsciiPack do
141
143
  # format_array 0xffffffff, T.array32
142
144
  end
143
145
 
146
+ it "recursive array" do
147
+ array = [0]
148
+ 1000.times {
149
+ array = [array]
150
+ }
151
+ ap = AsciiPack.pack(array)
152
+ expect(AsciiPack.unpack(ap)).to eq(array)
153
+ end
154
+
144
155
  it "nil" do
145
156
  format nil, T.nil, 1
146
157
  end
@@ -161,6 +172,11 @@ def format (object, first, length)
161
172
  expect(AsciiPack.unpack(ap)).to eq(object)
162
173
  end
163
174
 
175
+ def check_each_other (object, ap)
176
+ expect(AsciiPack.pack(object)).to eq(ap)
177
+ expect(AsciiPack.unpack(ap)).to eq(object)
178
+ end
179
+
164
180
  def format_map (count, first)
165
181
  map = {}
166
182
  count.times{ |i| map[i] = 0 }
data/spec/spec_helper.rb CHANGED
@@ -15,9 +15,9 @@ T = OpenStruct.new({
15
15
  :float32 => 'k',
16
16
  :float64 => 'l',
17
17
  # (blank) => 'm',
18
- :bin8 => 'n',
19
- :bin16 => 'o',
20
- :bin32 => 'p',
18
+ :str8 => 'n',
19
+ :str16 => 'o',
20
+ :str32 => 'p',
21
21
  # (blank) => 'q',
22
22
  :map4 => 'r',
23
23
  :map8 => 's',
@@ -44,22 +44,22 @@ T = OpenStruct.new({
44
44
  :positive_fixint_D => 'D',
45
45
  :positive_fixint_E => 'E',
46
46
  :positive_fixint_F => 'F',
47
- :fixbin_0 => 'G',
48
- :fixbin_1 => 'H',
49
- :fixbin_2 => 'I',
50
- :fixbin_3 => 'J',
51
- :fixbin_4 => 'K',
52
- :fixbin_5 => 'L',
53
- :fixbin_6 => 'M',
54
- :fixbin_7 => 'N',
55
- :fixbin_8 => 'O',
56
- :fixbin_9 => 'P',
57
- :fixbin_A => 'Q',
58
- :fixbin_B => 'R',
59
- :fixbin_C => 'S',
60
- :fixbin_D => 'T',
61
- :fixbin_E => 'U',
62
- :fixbin_F => 'V',
47
+ :fixstr_0 => 'G',
48
+ :fixstr_1 => 'H',
49
+ :fixstr_2 => 'I',
50
+ :fixstr_3 => 'J',
51
+ :fixstr_4 => 'K',
52
+ :fixstr_5 => 'L',
53
+ :fixstr_6 => 'M',
54
+ :fixstr_7 => 'N',
55
+ :fixstr_8 => 'O',
56
+ :fixstr_9 => 'P',
57
+ :fixstr_A => 'Q',
58
+ :fixstr_B => 'R',
59
+ :fixstr_C => 'S',
60
+ :fixstr_D => 'T',
61
+ :fixstr_E => 'U',
62
+ :fixstr_F => 'V',
63
63
  :nil => 'W',
64
64
  :false => 'X',
65
65
  :true => 'Y',
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asciipack
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ksss
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-10-16 00:00:00.000000000 Z
11
+ date: 2013-10-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,10 +52,25 @@ dependencies:
52
52
  - - ~>
53
53
  - !ruby/object:Gem::Version
54
54
  version: '2.11'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake-compiler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 0.8.3
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 0.8.3
55
69
  description: AsciiPack is an object serialization inspired by MessagePack.
56
70
  email: co000ri@gmail.com
57
71
  executables: []
58
- extensions: []
72
+ extensions:
73
+ - ext/asciipack/extconf.rb
59
74
  extra_rdoc_files: []
60
75
  files:
61
76
  - .gitignore
@@ -64,9 +79,13 @@ files:
64
79
  - README.md
65
80
  - Rakefile
66
81
  - asciipack.gemspec
82
+ - ext/asciipack/extconf.rb
83
+ - ext/asciipack/init.c
84
+ - ext/asciipack/packer.c
85
+ - ext/asciipack/packer.h
86
+ - ext/asciipack/unpacker.c
87
+ - ext/asciipack/unpacker.h
67
88
  - lib/asciipack.rb
68
- - lib/asciipack/packer.rb
69
- - lib/asciipack/unpacker.rb
70
89
  - lib/asciipack/version.rb
71
90
  - spec/bench.rb
72
91
  - spec/format_spec.rb