sereal 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/rsrl +5 -3
- data/ext/sereal/buffer.h +133 -57
- data/ext/sereal/decode.c +224 -187
- data/ext/sereal/encode.c +187 -184
- data/ext/sereal/proto.h +1 -1
- data/ext/sereal/sereal.c +18 -2
- data/ext/sereal/sereal.h +34 -23
- metadata +2 -2
data/ext/sereal/encode.c
CHANGED
@@ -51,92 +51,94 @@ static void s_append_nil(sereal_t *s, VALUE object);
|
|
51
51
|
static void s_default_writer(sereal_t *s, VALUE object);
|
52
52
|
|
53
53
|
void s_init_writers(void) {
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
54
|
+
u32 i;
|
55
|
+
for (i = 0; i < sizeof(WRITER)/sizeof(WRITER[0]); i++)
|
56
|
+
WRITER[i] = s_default_writer;
|
57
|
+
|
58
|
+
WRITER[T_FIXNUM] = s_append_integer;
|
59
|
+
WRITER[T_BIGNUM] = s_append_integer;
|
60
|
+
WRITER[T_FLOAT] = s_append_double;
|
61
|
+
WRITER[T_OBJECT] = s_append_object;
|
62
|
+
WRITER[T_REGEXP] = s_append_regexp;
|
63
|
+
WRITER[T_STRING] = s_append_rb_string;
|
64
|
+
WRITER[T_ARRAY] = s_append_array;
|
65
|
+
WRITER[T_HASH] = s_append_hash;
|
66
|
+
WRITER[T_SYMBOL] = s_append_symbol;
|
67
|
+
WRITER[T_TRUE] = s_append_true;
|
68
|
+
WRITER[T_FALSE] = s_append_false;
|
69
|
+
WRITER[T_NIL] = s_append_nil;
|
69
70
|
}
|
70
71
|
|
71
72
|
static void s_default_writer(sereal_t *s, VALUE object) {
|
72
|
-
|
73
|
+
s_raise(s,rb_eTypeError, "invalid type for input %s",rb_obj_classname(object));
|
73
74
|
}
|
74
75
|
|
75
76
|
|
76
77
|
static inline void s_append_varint(sereal_t *s,u64 n) {
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
78
|
+
while (n >= 0x80) {
|
79
|
+
s_append_u8(s,((n & 0x7f) | 0x80));
|
80
|
+
n >>= 7;
|
81
|
+
}
|
82
|
+
s_append_u8(s,n);
|
82
83
|
}
|
83
84
|
|
84
85
|
static inline void s_append_hdr_with_varint(sereal_t *s,u8 hdr, u64 n) {
|
85
|
-
|
86
|
-
|
86
|
+
s_append_u8(s,hdr);
|
87
|
+
s_append_varint(s,n);
|
87
88
|
}
|
88
89
|
|
89
90
|
static inline void s_append_zigzag(sereal_t *s,u64 n) {
|
90
|
-
|
91
|
-
|
91
|
+
s_append_hdr_with_varint(s,SRL_HDR_ZIGZAG,
|
92
|
+
(n << 1) ^ (n >> (sizeof(long) * 8 - 1)));
|
92
93
|
}
|
93
94
|
|
94
95
|
static inline void s_append_string(sereal_t *s,u8 *string, u32 len,u8 is_utf8) {
|
95
|
-
|
96
|
-
|
96
|
+
if (is_utf8) {
|
97
|
+
s_append_hdr_with_varint(s,SRL_HDR_STR_UTF8,len);
|
98
|
+
} else {
|
99
|
+
if (len < SRL_MASK_SHORT_BINARY_LEN) {
|
100
|
+
s_append_u8(s,SRL_HDR_SHORT_BINARY_LOW | (u8)len);
|
97
101
|
} else {
|
98
|
-
|
99
|
-
s_append_u8(s,SRL_HDR_SHORT_BINARY_LOW | (u8)len);
|
100
|
-
} else {
|
101
|
-
s_append_hdr_with_varint(s,SRL_HDR_BINARY,len);
|
102
|
-
}
|
102
|
+
s_append_hdr_with_varint(s,SRL_HDR_BINARY,len);
|
103
103
|
}
|
104
|
-
|
104
|
+
}
|
105
|
+
s_append(s,string,len);
|
105
106
|
}
|
106
107
|
|
107
108
|
static void s_append_rb_string(sereal_t *s, VALUE object) {
|
108
|
-
|
109
|
-
|
110
|
-
|
109
|
+
s_append_string(s,RSTRING_PTR(object),
|
110
|
+
RSTRING_LEN(object),
|
111
|
+
(is_ascii_string(object) ? FALSE : TRUE));
|
111
112
|
}
|
112
113
|
|
113
114
|
#define REF_THRESH(thresh,low,high) \
|
114
|
-
do {
|
115
|
+
do { \
|
115
116
|
if (len < (thresh)) \
|
116
|
-
|
117
|
+
s_append_u8(s, low | (u8) len); \
|
117
118
|
else \
|
118
|
-
|
119
|
-
} while(0);
|
119
|
+
s_append_hdr_with_varint(s,high,len); \
|
120
|
+
} while(0);
|
121
|
+
|
120
122
|
static void s_append_array(sereal_t *s, VALUE object) {
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
123
|
+
u32 i,len = RARRAY_LEN(object);
|
124
|
+
REF_THRESH(SRL_MASK_ARRAYREF_COUNT,SRL_HDR_ARRAYREF,SRL_HDR_ARRAY);
|
125
|
+
|
126
|
+
for (i = 0; i < len; i++)
|
127
|
+
rb_object_to_sereal(s,rb_ary_entry(object,i));
|
126
128
|
}
|
127
129
|
|
128
130
|
|
129
131
|
int s_hash_foreach(VALUE key, VALUE value, VALUE sereal_t_object) {
|
130
|
-
|
131
|
-
return ST_CONTINUE;
|
132
|
-
rb_object_to_sereal((sereal_t *) sereal_t_object,key);
|
133
|
-
rb_object_to_sereal((sereal_t *) sereal_t_object,value);
|
132
|
+
if (key == Qundef)
|
134
133
|
return ST_CONTINUE;
|
134
|
+
rb_object_to_sereal((sereal_t *) sereal_t_object,key);
|
135
|
+
rb_object_to_sereal((sereal_t *) sereal_t_object,value);
|
136
|
+
return ST_CONTINUE;
|
135
137
|
}
|
136
138
|
static void s_append_hash(sereal_t *s, VALUE object) {
|
137
|
-
|
138
|
-
|
139
|
-
|
139
|
+
u32 len = RHASH_SIZE(object);
|
140
|
+
REF_THRESH(SRL_MASK_HASHREF_COUNT,SRL_HDR_HASHREF,SRL_HDR_HASH);
|
141
|
+
rb_hash_foreach(object, s_hash_foreach, (VALUE) s);
|
140
142
|
}
|
141
143
|
#undef REF_THRESH
|
142
144
|
|
@@ -158,67 +160,67 @@ static void s_append_object(sereal_t *s, VALUE object) {
|
|
158
160
|
|
159
161
|
// <PATTERN-STR-TAG> <MODIFIERS-STR-TAG>
|
160
162
|
static void s_append_regexp(sereal_t *s, VALUE object) {
|
161
|
-
|
162
|
-
|
163
|
-
|
163
|
+
s_append_u8(s,SRL_HDR_REGEXP);
|
164
|
+
rb_encoding *enc = rb_enc_get(object);
|
165
|
+
VALUE pattern;
|
164
166
|
#ifndef RREGEXP_SRC_PTR
|
165
|
-
|
166
|
-
|
167
|
+
VALUE string = RREGEXP_SRC(object);
|
168
|
+
pattern = rb_enc_str_new(RSTRING_PTR(string),RSTRING_LEN(string),enc);
|
167
169
|
#else
|
168
|
-
|
170
|
+
pattern = rb_enc_str_new(RREGEXP_SRC_PTR(object),RREGEXP_SRC_LEN(object), enc);
|
169
171
|
#endif
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
172
|
+
s_append_rb_string(s,pattern);
|
173
|
+
|
174
|
+
int flags = rb_reg_options(object);
|
175
|
+
VALUE f = rb_str_new("",0);
|
176
|
+
if (flags & IGNORECASE)
|
177
|
+
rb_str_cat(f,"i",1);
|
178
|
+
if (flags & EXTENDED)
|
179
|
+
rb_str_cat(f,"x",1);
|
180
|
+
if (flags & MULTILINE)
|
181
|
+
rb_str_cat(f,"m",1);
|
182
|
+
s_append_rb_string(s,f);
|
181
183
|
}
|
182
184
|
|
183
185
|
|
184
186
|
static void s_append_integer(sereal_t *s, VALUE object) {
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
}
|
195
|
-
} else {
|
196
|
-
if (v > -17)
|
197
|
-
s_append_u8(s,SRL_HDR_NEG_LOW | ((u8) v + 32));
|
198
|
-
else
|
199
|
-
s_append_zigzag(s,v);
|
187
|
+
long long v = FIXNUM_P(object) ? FIX2LONG(object) : rb_num2ll(object);
|
188
|
+
if (v >= 0) {
|
189
|
+
if (v < 16)
|
190
|
+
s_append_u8(s,SRL_HDR_POS_LOW | (u8) v);
|
191
|
+
else {
|
192
|
+
if (!FIXNUM_P(object))
|
193
|
+
s_append_hdr_with_varint(s,SRL_HDR_VARINT,NUM2ULL(object));
|
194
|
+
else
|
195
|
+
s_append_hdr_with_varint(s,SRL_HDR_VARINT,v);
|
200
196
|
}
|
197
|
+
} else {
|
198
|
+
if (v > -17)
|
199
|
+
s_append_u8(s,SRL_HDR_NEG_LOW | ((u8) v + 32));
|
200
|
+
else
|
201
|
+
s_append_zigzag(s,v);
|
202
|
+
}
|
201
203
|
}
|
202
204
|
static void s_append_double(sereal_t *s, VALUE object) {
|
203
|
-
|
204
|
-
|
205
|
-
|
205
|
+
double d = NUM2DBL(object);
|
206
|
+
s_append_u8(s,SRL_HDR_DOUBLE);
|
207
|
+
s_append(s,&d,sizeof(d));
|
206
208
|
}
|
207
209
|
static void s_append_true(sereal_t *s, VALUE object) {
|
208
|
-
|
210
|
+
s_append_u8(s,SRL_HDR_TRUE);
|
209
211
|
}
|
210
212
|
static void s_append_false(sereal_t *s, VALUE object) {
|
211
|
-
|
213
|
+
s_append_u8(s,SRL_HDR_FALSE);
|
212
214
|
}
|
213
215
|
static void s_append_nil(sereal_t *s, VALUE object) {
|
214
|
-
|
216
|
+
s_append_u8(s,SRL_HDR_UNDEF);
|
215
217
|
}
|
216
218
|
|
217
219
|
/* writer function pointers */
|
218
220
|
static void rb_object_to_sereal(sereal_t *s, VALUE object) {
|
219
|
-
|
220
|
-
|
221
|
-
|
221
|
+
S_RECURSE_INC(s);
|
222
|
+
(*WRITER[TYPE(object)])(s,object);
|
223
|
+
S_RECURSE_DEC(s);
|
222
224
|
}
|
223
225
|
|
224
226
|
// https://github.com/Sereal/Sereal/blob/master/Perl/Encoder/srl_encoder.c#L623
|
@@ -238,99 +240,100 @@ void fixup_varint_from_to(u8 *varint_start, u8 *varint_end, u32 number) {
|
|
238
240
|
}
|
239
241
|
|
240
242
|
VALUE method_sereal_encode(VALUE self, VALUE args) {
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
243
|
+
u32 argc = RARRAY_LEN(args);
|
244
|
+
if (argc < 1)
|
245
|
+
rb_raise(rb_eArgError,"need at least 1 argument (object)");
|
246
|
+
|
247
|
+
sereal_t *s = s_create();
|
248
|
+
VALUE payload = rb_ary_shift(args);
|
249
|
+
VALUE compress = Qfalse;
|
250
|
+
if (argc == 2)
|
251
|
+
compress = rb_ary_shift(args);
|
252
|
+
u8 do_compress;
|
253
|
+
u8 version = SRL_PROTOCOL_VERSION;
|
254
|
+
|
255
|
+
if (TYPE(compress) == T_FIXNUM) {
|
256
|
+
do_compress = (u8) FIX2LONG(compress);
|
257
|
+
} else {
|
258
|
+
do_compress = (compress == Qtrue ? 1 : 0);
|
259
|
+
}
|
258
260
|
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
261
|
+
switch(do_compress) {
|
262
|
+
case __SNAPPY:
|
263
|
+
version |= SRL_PROTOCOL_ENCODING_SNAPPY;
|
264
|
+
break;
|
265
|
+
case __SNAPPY_INCR:
|
266
|
+
version |= SRL_PROTOCOL_ENCODING_SNAPPY_INCR;
|
267
|
+
break;
|
268
|
+
case __RAW:
|
269
|
+
default:
|
270
|
+
version |= SRL_PROTOCOL_ENCODING_RAW;
|
271
|
+
}
|
272
|
+
// setup header
|
273
|
+
s_append_u32(s,SRL_MAGIC_STRING_LILIPUTIAN);
|
274
|
+
s_append_u8(s,version);
|
275
|
+
s_append_u8(s,0x0);
|
276
|
+
u32 s_header_len = s->pos;
|
277
|
+
|
278
|
+
// serialize
|
279
|
+
rb_object_to_sereal(s,payload);
|
280
|
+
|
281
|
+
// compress
|
282
|
+
if (do_compress) {
|
283
|
+
u8 *start_compressed_varint = NULL, *start_un_compressed_varint= NULL, *compressed, *end;
|
284
|
+
u32 compressed_len = 0;
|
285
|
+
u32 compressed_len_varint = 0;
|
286
|
+
u32 un_compressed_len_varint = 0;
|
287
|
+
u32 s_body_len = s->size - s_header_len;
|
288
|
+
// snappy <compressed blob>
|
289
|
+
// snappy incr <varint blob len><compressed blob>
|
290
|
+
if (do_compress == __SNAPPY || do_compress == __SNAPPY_INCR) {
|
291
|
+
compressed_len = csnappy_max_compressed_length(s_body_len);
|
269
292
|
}
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
// serialize
|
277
|
-
rb_object_to_sereal(s,payload);
|
278
|
-
// compress
|
279
|
-
if (do_compress) {
|
280
|
-
u8 *start_compressed_varint = NULL, *start_un_compressed_varint= NULL, *compressed, *end;
|
281
|
-
u32 compressed_len = 0;
|
282
|
-
u32 compressed_len_varint = 0;
|
283
|
-
u32 un_compressed_len_varint = 0;
|
284
|
-
u32 s_body_len = s->size - s_header_len;
|
285
|
-
// snappy <compressed blob>
|
286
|
-
// snappy incr <varint blob len><compressed blob>
|
287
|
-
// lz4 <varint uncompressed len><varint blob len><compressed blob>
|
288
|
-
if (do_compress == __SNAPPY || do_compress == __SNAPPY_INCR) {
|
289
|
-
compressed_len = csnappy_max_compressed_length(s_body_len);
|
290
|
-
}
|
291
|
-
|
292
|
-
if (do_compress == __SNAPPY_INCR) {
|
293
|
-
start_compressed_varint = s_get_p(s);
|
294
|
-
s_append_varint(s,compressed_len);
|
295
|
-
end = s_get_p(s);
|
296
|
-
compressed_len_varint = end - start_compressed_varint;
|
297
|
-
}
|
298
|
-
|
299
|
-
compressed = alloc_or_raise(compressed_len + s_header_len + compressed_len_varint + un_compressed_len_varint);
|
300
|
-
COPY(s_get_p_at_pos(s,0,0),compressed,s_header_len);
|
301
|
-
|
302
|
-
if (start_un_compressed_varint)
|
303
|
-
COPY(start_un_compressed_varint,
|
304
|
-
compressed + s_header_len,
|
305
|
-
un_compressed_len_varint);
|
306
|
-
if (start_compressed_varint)
|
307
|
-
COPY(start_compressed_varint,
|
308
|
-
compressed + s_header_len + un_compressed_len_varint,
|
309
|
-
compressed_len_varint);
|
310
|
-
|
311
|
-
u8 *start = s_get_p_at_pos(s,s_header_len,1);
|
312
|
-
u8 *working_buf = alloc_or_raise(CSNAPPY_WORKMEM_BYTES);
|
313
|
-
csnappy_compress(start,
|
314
|
-
s_body_len,
|
315
|
-
(compressed + s_header_len + compressed_len_varint + un_compressed_len_varint),
|
316
|
-
&compressed_len,
|
317
|
-
working_buf,
|
318
|
-
CSNAPPY_WORKMEM_BYTES_POWER_OF_TWO);
|
319
|
-
|
320
|
-
free(working_buf);
|
321
|
-
if (compressed_len == 0)
|
322
|
-
s_raise(s,rb_eTypeError,"failed to compress");
|
323
|
-
if (start_compressed_varint)
|
324
|
-
fixup_varint_from_to(compressed + s_header_len + un_compressed_len_varint,
|
325
|
-
compressed + s_header_len + un_compressed_len_varint + compressed_len_varint - 1,
|
326
|
-
compressed_len);
|
327
|
-
free(s->data);
|
328
|
-
s->data = compressed;
|
329
|
-
s->size = compressed_len + s_header_len + compressed_len_varint + un_compressed_len_varint;
|
330
|
-
s->pos = s->size;
|
293
|
+
|
294
|
+
if (do_compress == __SNAPPY_INCR) {
|
295
|
+
start_compressed_varint = s_end_p(s);
|
296
|
+
s_append_varint(s,compressed_len);
|
297
|
+
end = s_end_p(s);
|
298
|
+
compressed_len_varint = end - start_compressed_varint;
|
331
299
|
}
|
332
300
|
|
333
|
-
|
334
|
-
|
335
|
-
|
301
|
+
compressed = s_alloc_or_raise(s,compressed_len + s_header_len + compressed_len_varint + un_compressed_len_varint);
|
302
|
+
|
303
|
+
COPY(s_get_p_at_pos(s,0,0),compressed,s_header_len);
|
304
|
+
|
305
|
+
if (start_un_compressed_varint)
|
306
|
+
COPY(start_un_compressed_varint,
|
307
|
+
compressed + s_header_len,
|
308
|
+
un_compressed_len_varint);
|
309
|
+
if (start_compressed_varint)
|
310
|
+
COPY(start_compressed_varint,
|
311
|
+
compressed + s_header_len + un_compressed_len_varint,
|
312
|
+
compressed_len_varint);
|
313
|
+
|
314
|
+
u8 *start = s_get_p_at_pos(s,s_header_len,1);
|
315
|
+
u8 *working_buf = s_alloc_or_raise(s,CSNAPPY_WORKMEM_BYTES);
|
316
|
+
csnappy_compress(start,
|
317
|
+
s_body_len,
|
318
|
+
(compressed + s_header_len + compressed_len_varint + un_compressed_len_varint),
|
319
|
+
&compressed_len,
|
320
|
+
working_buf,
|
321
|
+
CSNAPPY_WORKMEM_BYTES_POWER_OF_TWO);
|
322
|
+
|
323
|
+
free(working_buf);
|
324
|
+
if (compressed_len == 0)
|
325
|
+
s_raise(s,rb_eTypeError,"failed to compress");
|
326
|
+
if (start_compressed_varint)
|
327
|
+
fixup_varint_from_to(compressed + s_header_len + un_compressed_len_varint,
|
328
|
+
compressed + s_header_len + un_compressed_len_varint + compressed_len_varint - 1,
|
329
|
+
compressed_len);
|
330
|
+
free(s->data);
|
331
|
+
s->data = compressed;
|
332
|
+
s->size = compressed_len + s_header_len + compressed_len_varint + un_compressed_len_varint;
|
333
|
+
s->pos = s->size;
|
334
|
+
}
|
335
|
+
|
336
|
+
VALUE result = rb_str_new(s->data,s->size);
|
337
|
+
s_destroy(s);
|
338
|
+
return result;
|
336
339
|
}
|
data/ext/sereal/proto.h
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#define SRL_MAGIC_STRING "=srl" /* Magic string for header. Every packet starts with this */
|
2
2
|
#define SRL_MAGIC_STRING_LILIPUTIAN 0x6c72733d /* SRL_MAGIC_STRING as a little endian integer */
|
3
3
|
|
4
|
-
#define SRL_PROTOCOL_VERSION (
|
4
|
+
#define SRL_PROTOCOL_VERSION ( 2 ) /* this is the first. for some reason we did not use 0 */
|
5
5
|
#define SRL_PROTOCOL_VERSION_BITS ( 4 ) /* how many bits we use for the version, the rest go to the encoding */
|
6
6
|
#define SRL_PROTOCOL_VERSION_MASK ( ( 1 << SRL_PROTOCOL_VERSION_BITS ) - 1 )
|
7
7
|
|