tinybits 0.2.0 → 0.4.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.
- checksums.yaml +4 -4
- data/ext/tinybits/extconf.rb +1 -0
- data/ext/tinybits/test_date.rb +28 -3
- data/ext/tinybits/tinybits.h +8 -5
- data/ext/tinybits/tinybits_ext.c +54 -1
- data/lib/tinybits/version.rb +1 -1
- data/lib/tinybits.rb +13 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 579aa574466ff4f72f4e9fa59940d3d14fc773404cb73296b2b1498551da6d2f
|
4
|
+
data.tar.gz: 5edf98872ab8d59a3868b0dc6e3b05271d8dbdba7664afc039ca219820a7b247
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 887b0b5c435cd7da039af2b370f680c5266c06cad1db665e54436f81a22172837495739c051ccea3050a446e055ca24a9198269a51bdb7005fec79d398c37758
|
7
|
+
data.tar.gz: 44c1cd7a40ccf330d8ca96a5c7203b6ce60c07c00c3580fe28440ef0b62c6c083ad4417143a52afce3ae0553eefbc7a9d9035e7011d13557f682704be6f5ad5d
|
data/ext/tinybits/extconf.rb
CHANGED
data/ext/tinybits/test_date.rb
CHANGED
@@ -7,19 +7,30 @@ t = [Time.now, nil, true, false]
|
|
7
7
|
|
8
8
|
|
9
9
|
|
10
|
-
|
10
|
+
=begin
|
11
11
|
puts packer.dump(t).bytesize
|
12
12
|
|
13
13
|
puts t
|
14
14
|
puts t2 = unpacker.unpack(packer.pack(t))
|
15
15
|
puts t == t2
|
16
|
-
|
16
|
+
=end
|
17
|
+
|
18
|
+
class User
|
19
|
+
def initialize(name:, title:)
|
20
|
+
@name = name
|
21
|
+
@title = title
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_tinybits
|
25
|
+
{"name" => @name, "title" => @title}
|
26
|
+
end
|
27
|
+
end
|
17
28
|
|
18
29
|
objects = [{"abc": 123}, {"abc": [1, 2, "abc"]}, ["xyz", "abc", "xyz", 7.6] ]
|
19
30
|
|
20
31
|
puts "----------------"
|
21
32
|
|
22
|
-
packer.reset
|
33
|
+
#packer.reset
|
23
34
|
|
24
35
|
objects.each do |obj|
|
25
36
|
puts packer << obj
|
@@ -31,7 +42,21 @@ puts buffer.bytesize
|
|
31
42
|
|
32
43
|
unpacker.buffer = buffer
|
33
44
|
|
45
|
+
|
34
46
|
while(value = unpacker.pop)
|
35
47
|
pp value
|
36
48
|
puts "+++++++++++++++++++++++++"
|
37
49
|
end
|
50
|
+
|
51
|
+
packer.reset
|
52
|
+
|
53
|
+
user = User.new(name: "Mohamed", title: "Father")
|
54
|
+
|
55
|
+
data = { "user" => user, "tags" => ["user", "Father"] }
|
56
|
+
|
57
|
+
pp user
|
58
|
+
pp user.to_tinybits
|
59
|
+
packed = packer.pack(data)
|
60
|
+
puts packed.bytesize
|
61
|
+
pp unpacker.unpack(packed)
|
62
|
+
|
data/ext/tinybits/tinybits.h
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/**
|
2
2
|
* TinyBits Amalgamated Header
|
3
|
-
* Generated on:
|
3
|
+
* Generated on: Sun May 4 05:43:30 PM CEST 2025
|
4
4
|
*/
|
5
5
|
|
6
6
|
#ifndef TINY_BITS_H
|
@@ -89,8 +89,11 @@ typedef struct HashTable {
|
|
89
89
|
|
90
90
|
static inline uint32_t fast_hash_32(const char* str, uint16_t len) {
|
91
91
|
uint32_t hash = len;
|
92
|
-
hash = (hash <<
|
93
|
-
|
92
|
+
hash = (hash << 24) |
|
93
|
+
((unsigned char)str[0] << 16) |
|
94
|
+
((unsigned char)str[1] << 8 ) |
|
95
|
+
((unsigned char)str[len-1]);
|
96
|
+
//hash ^= (((unsigned char)str[len-2] << 24) | ((unsigned char)str[len-1] << 16));
|
94
97
|
return hash;
|
95
98
|
}
|
96
99
|
|
@@ -652,7 +655,7 @@ static inline int pack_str(tiny_bits_packer *encoder, char* str, uint32_t str_le
|
|
652
655
|
HashEntry entry = encoder->encode_table.cache[index - 1];
|
653
656
|
if (hash_code == entry.hash
|
654
657
|
&& str_len == entry.length
|
655
|
-
&&
|
658
|
+
&& fast_memcmp(str, encoder->buffer + entry.offset, str_len) == 0 ) {
|
656
659
|
id = index - 1;
|
657
660
|
found = 1;
|
658
661
|
break;
|
@@ -1052,7 +1055,7 @@ static inline enum tiny_bits_type _unpack_str(tiny_bits_unpacker *decoder, uint8
|
|
1052
1055
|
}
|
1053
1056
|
value->str_blob_val.id = 0;
|
1054
1057
|
// Handle new string (not deduplicated)
|
1055
|
-
if(decoder->strings_count < TB_HASH_CACHE_SIZE){
|
1058
|
+
if(decoder->strings_count < TB_HASH_CACHE_SIZE && len >= 2 && len <= 128){
|
1056
1059
|
if (decoder->strings_count >= decoder->strings_size) {
|
1057
1060
|
size_t new_size = decoder->strings_size * 2;
|
1058
1061
|
void *new_strings = realloc(decoder->strings, new_size * sizeof(*decoder->strings));
|
data/ext/tinybits/tinybits_ext.c
CHANGED
@@ -4,8 +4,23 @@
|
|
4
4
|
#include "tinybits.h"
|
5
5
|
|
6
6
|
// Ruby module and classes
|
7
|
+
/*
|
8
|
+
* Document-module: TinyBits
|
9
|
+
*
|
10
|
+
* A Ruby extension for fast binary serialization and deserialization of Ruby objects.
|
11
|
+
*/
|
7
12
|
VALUE rb_mTinyBits;
|
13
|
+
/*
|
14
|
+
* Document-class: TinyBits::Packer
|
15
|
+
*
|
16
|
+
* The Packer class handles serialization of Ruby objects to the TinyBits binary format.
|
17
|
+
*/
|
8
18
|
VALUE rb_cPacker;
|
19
|
+
/*
|
20
|
+
* Document-class: TinyBits::Unpacker
|
21
|
+
*
|
22
|
+
* The Unpacker class handles deserialization of TinyBits binary format to Ruby objects.
|
23
|
+
*/
|
9
24
|
VALUE rb_cUnpacker;
|
10
25
|
|
11
26
|
// Forward declarations
|
@@ -75,6 +90,13 @@ static VALUE rb_packer_alloc(VALUE klass) {
|
|
75
90
|
return TypedData_Wrap_Struct(klass, &packer_data_type, packer_data);
|
76
91
|
}
|
77
92
|
|
93
|
+
/*
|
94
|
+
* Document-method: initialize
|
95
|
+
*
|
96
|
+
* Initializes a new Packer object
|
97
|
+
*
|
98
|
+
* @return [Packer] The initialized packer object.
|
99
|
+
*/
|
78
100
|
static VALUE rb_packer_init(VALUE self) {
|
79
101
|
PackerData* packer_data;
|
80
102
|
TypedData_Get_Struct(self, PackerData, &packer_data_type, packer_data);
|
@@ -131,13 +153,27 @@ static inline int pack_ruby_object_recursive(tiny_bits_packer* packer, VALUE obj
|
|
131
153
|
double unixtime = NUM2DBL(rb_funcall(obj, rb_intern("to_f"), 0));
|
132
154
|
return pack_datetime(packer, unixtime, FIX2INT(rb_time_utc_offset(obj)));
|
133
155
|
}
|
156
|
+
if(rb_respond_to(obj, rb_intern("to_tinybits"))){
|
157
|
+
VALUE custom_obj = rb_funcall(obj, rb_intern("to_tinybits"), 0);
|
158
|
+
return pack_ruby_object_recursive(packer, custom_obj, context);
|
159
|
+
}
|
134
160
|
//printf("Unsupported type encountered during packing: %s", rb_obj_classname(obj));
|
135
161
|
rb_warn("Unsupported type encountered during packing: %s", rb_obj_classname(obj));
|
136
162
|
return 0;
|
137
163
|
}
|
138
164
|
}
|
139
165
|
|
140
|
-
|
166
|
+
/*
|
167
|
+
* Document-method: pack
|
168
|
+
*
|
169
|
+
* Packs a Ruby object into a binary string.
|
170
|
+
* Supports Ruby types: String, Array, Hash, Integer, Float, nil, true, false, Symbol, and Time.
|
171
|
+
* Objects can implement a `to_tinybits` method to provide custom serialization.
|
172
|
+
*
|
173
|
+
* @param obj [Object] The Ruby object to pack.
|
174
|
+
* @return [String] The packed binary string (frozen).
|
175
|
+
* @raise [RuntimeError] If packing fails due to unsupported types or other errors.
|
176
|
+
*/
|
141
177
|
static VALUE rb_pack(VALUE self, VALUE obj) {
|
142
178
|
PackerData* packer_data;
|
143
179
|
TypedData_Get_Struct(self, PackerData, &packer_data_type, packer_data);
|
@@ -165,6 +201,16 @@ static VALUE rb_pack(VALUE self, VALUE obj) {
|
|
165
201
|
return result;
|
166
202
|
}
|
167
203
|
|
204
|
+
/*
|
205
|
+
* Document-method: push
|
206
|
+
*
|
207
|
+
* Appends a packed object to the current buffer.
|
208
|
+
* Inserts a separator when appending to non-empty buffer.
|
209
|
+
*
|
210
|
+
* @param obj [Object] The Ruby object to append.
|
211
|
+
* @return [Integer] The number of bytes added to the buffer.
|
212
|
+
* @raise [RuntimeError] If packing fails.
|
213
|
+
*/
|
168
214
|
static VALUE rb_push(VALUE self, VALUE obj) {
|
169
215
|
PackerData* packer_data;
|
170
216
|
TypedData_Get_Struct(self, PackerData, &packer_data_type, packer_data);
|
@@ -195,6 +241,13 @@ static VALUE rb_push(VALUE self, VALUE obj) {
|
|
195
241
|
return INT2FIX(packer_data->packer->current_pos - initial_pos);
|
196
242
|
}
|
197
243
|
|
244
|
+
/*
|
245
|
+
* Document-method: to_s
|
246
|
+
*
|
247
|
+
* Returns the current packed buffer as a string.
|
248
|
+
*
|
249
|
+
* @return [String] The current packed buffer contents (frozen).
|
250
|
+
*/
|
198
251
|
static VALUE rb_to_s(VALUE self){
|
199
252
|
PackerData* packer_data;
|
200
253
|
TypedData_Get_Struct(self, PackerData, &packer_data_type, packer_data);
|
data/lib/tinybits/version.rb
CHANGED
data/lib/tinybits.rb
CHANGED
@@ -2,6 +2,19 @@ require_relative './tinybits/version'
|
|
2
2
|
require 'tinybits_ext'
|
3
3
|
|
4
4
|
module TinyBits
|
5
|
+
# packs an object to a binary string
|
6
|
+
# @param obj [Object] The Ruby object to pack.
|
7
|
+
# @return [String] The packed binary string (frozen).
|
8
|
+
# @raise [RuntimeError] If packing fails due to unsupported types or other errors.
|
9
|
+
# this is a convinience interface, a better way is to instantiate a TinyBits::Packer
|
10
|
+
# object and use its #pack method
|
5
11
|
def self.pack(object) = Packer.new.pack(object)
|
12
|
+
|
13
|
+
# unpacks an object from a binary string
|
14
|
+
# @param buffer [String] The Ruby string holding the packed buffer.
|
15
|
+
# @return [Object] The unpacked Ruby Object (all strings within the object will be frozen).
|
16
|
+
# @raise [RuntimeError] If unpacking fails due to unsupported types or malformed data.
|
17
|
+
# this is a convinience interface, a better way is to instantiate a TinyBits::Unpacker
|
18
|
+
# object and use its #unpack method
|
6
19
|
def self.unpack(buffer) = Unpacker.new.unpack(buffer)
|
7
20
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tinybits
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mohamed Hassan
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-05-
|
10
|
+
date: 2025-05-04 00:00:00.000000000 Z
|
11
11
|
dependencies: []
|
12
12
|
description: TinyBits is a Ruby gem that wraps the TinyBits C serializartion library,
|
13
13
|
offering Rubyists the power of serializion with intger/float compression and string
|