sereal 0.0.7 → 0.0.8
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.
- 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
|
|