capn_proto 0.0.1.alpha.4 → 0.0.1.alpha.5
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/README.md +48 -11
- data/Rakefile +1 -0
- data/ext/capn_proto/dynamic_list_builder.cc +123 -0
- data/ext/capn_proto/dynamic_list_builder.h +27 -0
- data/ext/capn_proto/dynamic_list_reader.cc +9 -0
- data/ext/capn_proto/dynamic_list_reader.h +2 -0
- data/ext/capn_proto/dynamic_object_builder.cc +57 -0
- data/ext/capn_proto/dynamic_object_builder.h +22 -0
- data/ext/capn_proto/dynamic_object_reader.h +1 -1
- data/ext/capn_proto/dynamic_struct_builder.cc +171 -0
- data/ext/capn_proto/dynamic_struct_builder.h +34 -0
- data/ext/capn_proto/dynamic_struct_reader.cc +9 -1
- data/ext/capn_proto/dynamic_struct_reader.h +2 -0
- data/ext/capn_proto/dynamic_value_builder.cc +53 -0
- data/ext/capn_proto/dynamic_value_builder.h +13 -0
- data/ext/capn_proto/exception.cc +6 -0
- data/ext/capn_proto/exception.h +2 -1
- data/ext/capn_proto/flat_array_message_reader.cc +61 -0
- data/ext/capn_proto/flat_array_message_reader.h +21 -0
- data/ext/capn_proto/init.cc +31 -14
- data/ext/capn_proto/malloc_message_builder.cc +51 -0
- data/ext/capn_proto/malloc_message_builder.h +21 -0
- data/ext/capn_proto/message_builder.cc +22 -0
- data/ext/capn_proto/message_builder.h +17 -0
- data/ext/capn_proto/stream_fd_message_reader.cc +7 -1
- data/ext/capn_proto/stream_fd_message_reader.h +1 -1
- data/ext/capn_proto/util.cc +5 -0
- data/ext/capn_proto/util.h +1 -0
- data/lib/capn_proto/version.rb +1 -1
- data/lib/capn_proto.rb +57 -4
- data/spec/capn_proto_spec.rb +73 -0
- data/spec/spec_helper.rb +8 -0
- metadata +18 -4
- data/ext/capn_proto/.ycm_extra_conf.pyc +0 -0
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -31,6 +31,33 @@ module AddressBook extend CapnProto::SchemaLoader
|
|
31
31
|
load_schema("addressbook.capnp")
|
32
32
|
end
|
33
33
|
|
34
|
+
def write_address_book(file)
|
35
|
+
addresses = AddressBook::AddressBook.new_message
|
36
|
+
people = addresses.initPeople(2)
|
37
|
+
|
38
|
+
alice = people[0]
|
39
|
+
alice.id = 123
|
40
|
+
alice.name = 'Alice'
|
41
|
+
alice.email = 'alice@example.com'
|
42
|
+
alice_phones = alice.initPhones(1)
|
43
|
+
alice_phones[0].number = "555-1212"
|
44
|
+
alice_phones[0].type = 'mobile'
|
45
|
+
alice.employment.school = "MIT"
|
46
|
+
|
47
|
+
bob = people[1]
|
48
|
+
bob.id = 456
|
49
|
+
bob.name = 'Bob'
|
50
|
+
bob.email = 'bob@example.com'
|
51
|
+
bob_phones = bob.initPhones(2)
|
52
|
+
bob_phones[0].number = "555-4567"
|
53
|
+
bob_phones[0].type = 'home'
|
54
|
+
bob_phones[1].number = "555-7654"
|
55
|
+
bob_phones[1].type = 'work'
|
56
|
+
bob.employment.unemployed = nil
|
57
|
+
|
58
|
+
addresses.write(file)
|
59
|
+
end
|
60
|
+
|
34
61
|
def print_address_book(file)
|
35
62
|
addresses = AddressBook::AddressBook.read_from(file)
|
36
63
|
|
@@ -41,22 +68,25 @@ def print_address_book(file)
|
|
41
68
|
puts "#{phone.type} : #{phone.number}"
|
42
69
|
end
|
43
70
|
|
44
|
-
|
45
|
-
|
46
|
-
if which == "unemployed"
|
71
|
+
if person.employment.unemployed?
|
47
72
|
puts "unemployed"
|
48
|
-
|
73
|
+
if person.employment.employer?
|
49
74
|
puts "employer: #{person.employment.employer}"
|
50
|
-
|
75
|
+
if person.employment.school?
|
51
76
|
puts "student at: #{person.employment.school}"
|
52
|
-
|
77
|
+
if person.employment.selfEmployed?
|
53
78
|
puts "self employed"
|
54
79
|
end
|
55
80
|
end
|
56
81
|
end
|
57
82
|
|
58
|
-
|
59
|
-
|
83
|
+
if __FILE__ == $0
|
84
|
+
file = File.open("addressbook.bin", "wb")
|
85
|
+
write_address_book(file)
|
86
|
+
|
87
|
+
file = File.open("addressbook.bin", "rb")
|
88
|
+
print_address_book(file)
|
89
|
+
end
|
60
90
|
```
|
61
91
|
|
62
92
|
# Status
|
@@ -64,11 +94,18 @@ print_address_book(file)
|
|
64
94
|
What's implemented:
|
65
95
|
- Schema parsing/loading
|
66
96
|
- Message reading
|
67
|
-
|
68
|
-
|
97
|
+
- From byte string
|
98
|
+
- From file descriptor
|
69
99
|
- Message writing
|
100
|
+
- To byte string
|
101
|
+
- To file descriptor
|
70
102
|
|
71
|
-
|
103
|
+
What's to come:
|
104
|
+
- More reading/writing mechanisms:
|
105
|
+
- Packing/unpacking
|
106
|
+
- Extensive test coverage
|
107
|
+
- Proper support for [JRuby][jruby]
|
108
|
+
- Support for RPC
|
72
109
|
|
73
110
|
[logo]: https://raw.github.com/cstrahan/capnp-ruby/master/media/captain_proto_small.png "Cap'n Proto"
|
74
111
|
[ruby]: http://www.ruby-lang.org/ "Ruby"
|
data/Rakefile
CHANGED
@@ -0,0 +1,123 @@
|
|
1
|
+
#include "ruby_capn_proto.h"
|
2
|
+
#include "dynamic_list_builder.h"
|
3
|
+
#include "dynamic_value_builder.h"
|
4
|
+
#include "dynamic_struct_reader.h"
|
5
|
+
#include "dynamic_struct_builder.h"
|
6
|
+
#include "exception.h"
|
7
|
+
#include "util.h"
|
8
|
+
#include "class_builder.h"
|
9
|
+
|
10
|
+
namespace ruby_capn_proto {
|
11
|
+
using WrappedType = capnp::DynamicList::Builder;
|
12
|
+
VALUE DynamicListBuilder::Class;
|
13
|
+
|
14
|
+
void DynamicListBuilder::Init() {
|
15
|
+
ClassBuilder("DynamicListBuilder", rb_cObject).
|
16
|
+
defineAlloc(&alloc).
|
17
|
+
defineMethod("[]", &get).
|
18
|
+
defineMethod("[]=", &set).
|
19
|
+
defineMethod("size", &size).
|
20
|
+
store(&Class);
|
21
|
+
}
|
22
|
+
|
23
|
+
VALUE DynamicListBuilder::alloc(VALUE klass) {
|
24
|
+
return Data_Wrap_Struct(klass, NULL, free, ruby_xmalloc(sizeof(WrappedType)));
|
25
|
+
}
|
26
|
+
|
27
|
+
void DynamicListBuilder::free(WrappedType* p) {
|
28
|
+
p->~Builder();
|
29
|
+
ruby_xfree(p);
|
30
|
+
}
|
31
|
+
|
32
|
+
WrappedType* DynamicListBuilder::unwrap(VALUE self) {
|
33
|
+
WrappedType* p;
|
34
|
+
Data_Get_Struct(self, WrappedType, p);
|
35
|
+
return p;
|
36
|
+
}
|
37
|
+
|
38
|
+
VALUE DynamicListBuilder::create(WrappedType builder, VALUE parent) {
|
39
|
+
auto rb_obj = alloc(Class);
|
40
|
+
WrappedType* wrapped = unwrap(rb_obj);
|
41
|
+
*wrapped = kj::mv(builder);
|
42
|
+
|
43
|
+
rb_iv_set(rb_obj, "parent", parent);
|
44
|
+
|
45
|
+
return rb_obj;
|
46
|
+
}
|
47
|
+
|
48
|
+
VALUE DynamicListBuilder::size(VALUE self) {
|
49
|
+
return INT2FIX(unwrap(self)->size());
|
50
|
+
}
|
51
|
+
|
52
|
+
VALUE DynamicListBuilder::get(VALUE self, VALUE rb_index) {
|
53
|
+
try {
|
54
|
+
return _get(self, rb_index);
|
55
|
+
} catch (kj::Exception ex) {
|
56
|
+
return Exception::raise(ex);
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
60
|
+
VALUE DynamicListBuilder::_get(VALUE self, VALUE rb_index) {
|
61
|
+
auto builder = *unwrap(self);
|
62
|
+
auto size = builder.size();
|
63
|
+
|
64
|
+
unsigned long index;
|
65
|
+
if (Util::isNegative(rb_index)) {
|
66
|
+
index = NUM2LONG(rb_index) % builder.size();
|
67
|
+
} else {
|
68
|
+
index = NUM2ULONG(rb_index);
|
69
|
+
}
|
70
|
+
|
71
|
+
// return DynamicValueBuilder::to_ruby(builder.get(field), self);
|
72
|
+
return DynamicValueBuilder::to_ruby(builder[index], self);
|
73
|
+
}
|
74
|
+
|
75
|
+
VALUE DynamicListBuilder::set(VALUE self, VALUE rb_index, VALUE rb_obj) {
|
76
|
+
try {
|
77
|
+
return _set(self, rb_index, rb_obj);
|
78
|
+
} catch (kj::Exception ex) {
|
79
|
+
return Exception::raise(ex);
|
80
|
+
}
|
81
|
+
}
|
82
|
+
|
83
|
+
VALUE DynamicListBuilder::_set(VALUE self, VALUE rb_index, VALUE rb_obj) {
|
84
|
+
VALUE klass = rb_funcall(rb_obj, rb_intern("class"), 0);
|
85
|
+
|
86
|
+
unsigned long field;
|
87
|
+
if (Util::isNegative(rb_index)) {
|
88
|
+
field = NUM2LONG(rb_index) % unwrap(self)->size();
|
89
|
+
} else {
|
90
|
+
field = NUM2ULONG(rb_index);
|
91
|
+
}
|
92
|
+
|
93
|
+
// TODO: handle assigning lists (see _setDynamicField)
|
94
|
+
if FIXNUM_P(rb_obj) {
|
95
|
+
if (Util::isNegative(rb_obj)) {
|
96
|
+
unwrap(self)->set(field, NUM2LONG(rb_obj));
|
97
|
+
} else {
|
98
|
+
unwrap(self)->set(field, NUM2ULONG(rb_obj));
|
99
|
+
}
|
100
|
+
} else if (RB_TYPE_P(rb_obj, T_FLOAT)) {
|
101
|
+
unwrap(self)->set(field, RFLOAT_VALUE(rb_obj));
|
102
|
+
} else if (rb_obj == Qtrue || rb_obj == Qfalse) {
|
103
|
+
unwrap(self)->set(field, (rb_obj == Qtrue) ? true : false);
|
104
|
+
} else if (RB_TYPE_P(rb_obj, T_STRING)) {
|
105
|
+
// TODO: need to ensure that the UTF8 char buffer is null terminated.
|
106
|
+
// consider something similar to rb_string_value_cstr,
|
107
|
+
// which grows the the buffer if necessary.
|
108
|
+
capnp::DynamicValue::Reader tmp =
|
109
|
+
capnp::Text::Reader(RSTRING_PTR(rb_obj), RSTRING_LEN(rb_obj));
|
110
|
+
unwrap(self)->set(field, tmp);
|
111
|
+
} else if (NIL_P(rb_obj)) {
|
112
|
+
unwrap(self)->set(field, capnp::VOID);
|
113
|
+
} else if (rb_equal(klass, DynamicStructReader::Class)) {
|
114
|
+
unwrap(self)->set(field, *DynamicStructReader::unwrap(rb_obj));
|
115
|
+
} else if (rb_equal(klass, DynamicStructBuilder::Class)) {
|
116
|
+
unwrap(self)->set(field, (*DynamicStructBuilder::unwrap(rb_obj)).asReader());
|
117
|
+
} else {
|
118
|
+
// TODO: raise "Non primitive type"
|
119
|
+
}
|
120
|
+
|
121
|
+
return rb_obj;
|
122
|
+
}
|
123
|
+
}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#ifndef DYNAMIC_LIST_BUILDER_H
|
2
|
+
#define DYNAMIC_LIST_BUILDER_H
|
3
|
+
|
4
|
+
#include "ruby_capn_proto.h"
|
5
|
+
|
6
|
+
namespace ruby_capn_proto {
|
7
|
+
class DynamicListBuilder {
|
8
|
+
public:
|
9
|
+
using WrappedType = capnp::DynamicList::Builder;
|
10
|
+
static void Init();
|
11
|
+
static VALUE alloc(VALUE klass);
|
12
|
+
static VALUE create(WrappedType reader, VALUE parent);
|
13
|
+
static void free(WrappedType* p);
|
14
|
+
static WrappedType* unwrap(VALUE self);
|
15
|
+
static VALUE which(VALUE self);
|
16
|
+
static VALUE get(VALUE self, VALUE index);
|
17
|
+
static VALUE set(VALUE self, VALUE index, VALUE rb_obj);
|
18
|
+
static VALUE size(VALUE self);
|
19
|
+
|
20
|
+
static VALUE Class;
|
21
|
+
private:
|
22
|
+
static VALUE _get(VALUE self, VALUE index);
|
23
|
+
static VALUE _set(VALUE self, VALUE index, VALUE rb_obj);
|
24
|
+
};
|
25
|
+
}
|
26
|
+
|
27
|
+
#endif /* DYNAMIC_LIST_BUILDER_H */
|
@@ -1,6 +1,7 @@
|
|
1
1
|
#include "ruby_capn_proto.h"
|
2
2
|
#include "dynamic_list_reader.h"
|
3
3
|
#include "dynamic_value_reader.h"
|
4
|
+
#include "exception.h"
|
4
5
|
#include "class_builder.h"
|
5
6
|
|
6
7
|
namespace ruby_capn_proto {
|
@@ -45,6 +46,14 @@ namespace ruby_capn_proto {
|
|
45
46
|
}
|
46
47
|
|
47
48
|
VALUE DynamicListReader::get(VALUE self, VALUE rb_index) {
|
49
|
+
try {
|
50
|
+
return _get(self, rb_index);
|
51
|
+
} catch (kj::Exception ex) {
|
52
|
+
return Exception::raise(ex);
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
VALUE DynamicListReader::_get(VALUE self, VALUE rb_index) {
|
48
57
|
auto reader = *unwrap(self);
|
49
58
|
auto index = FIX2INT(rb_index);
|
50
59
|
auto size = reader.size();
|
@@ -0,0 +1,57 @@
|
|
1
|
+
#include "ruby_capn_proto.h"
|
2
|
+
#include "dynamic_object_builder.h"
|
3
|
+
#include "dynamic_struct_builder.h"
|
4
|
+
#include "struct_schema.h"
|
5
|
+
#include "class_builder.h"
|
6
|
+
#include "util.h"
|
7
|
+
|
8
|
+
namespace ruby_capn_proto {
|
9
|
+
using WrappedType = capnp::ObjectPointer::Builder;
|
10
|
+
VALUE DynamicObjectBuilder::Class;
|
11
|
+
|
12
|
+
void DynamicObjectBuilder::Init() {
|
13
|
+
ClassBuilder("DynamicObjectBuilder", rb_cObject).
|
14
|
+
defineAlloc(&alloc).
|
15
|
+
defineMethod("as_struct", &as_struct).
|
16
|
+
store(&Class);
|
17
|
+
}
|
18
|
+
|
19
|
+
void DynamicObjectBuilder::free(WrappedType* p) {
|
20
|
+
p->~Builder();
|
21
|
+
ruby_xfree(p);
|
22
|
+
}
|
23
|
+
|
24
|
+
VALUE DynamicObjectBuilder::alloc(VALUE klass) {
|
25
|
+
return Data_Wrap_Struct(klass, NULL, free, ruby_xmalloc(sizeof(WrappedType)));
|
26
|
+
}
|
27
|
+
|
28
|
+
WrappedType* DynamicObjectBuilder::unwrap(VALUE self) {
|
29
|
+
WrappedType* p;
|
30
|
+
Data_Get_Struct(self, WrappedType, p);
|
31
|
+
return p;
|
32
|
+
}
|
33
|
+
|
34
|
+
VALUE DynamicObjectBuilder::create(WrappedType reader, VALUE parent) {
|
35
|
+
VALUE rb_obj = alloc(Class);
|
36
|
+
WrappedType* wrapped = unwrap(rb_obj);
|
37
|
+
*wrapped = kj::mv(reader);
|
38
|
+
|
39
|
+
rb_iv_set(rb_obj, "parent", parent);
|
40
|
+
|
41
|
+
return rb_obj;
|
42
|
+
}
|
43
|
+
|
44
|
+
VALUE DynamicObjectBuilder::as_struct(VALUE self, VALUE rb_schema) {
|
45
|
+
if (rb_respond_to(rb_schema, rb_intern("schema"))) {
|
46
|
+
rb_schema = rb_funcall(rb_schema, rb_intern("schema"), 0);
|
47
|
+
}
|
48
|
+
|
49
|
+
auto reader = *unwrap(self);
|
50
|
+
auto schema = *StructSchema::unwrap(rb_schema);
|
51
|
+
|
52
|
+
return DynamicStructBuilder::create(
|
53
|
+
reader.getAs<capnp::DynamicStruct>(schema),
|
54
|
+
self,
|
55
|
+
false);
|
56
|
+
}
|
57
|
+
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
#ifndef DYNAMIC_OBJECT_BUILDER_H
|
2
|
+
#define DYNAMIC_OBJECT_BUILDER_H
|
3
|
+
|
4
|
+
#include "ruby_capn_proto.h"
|
5
|
+
|
6
|
+
namespace ruby_capn_proto {
|
7
|
+
class DynamicObjectBuilder {
|
8
|
+
public:
|
9
|
+
using WrappedType = capnp::ObjectPointer::Builder;
|
10
|
+
static void Init();
|
11
|
+
static VALUE alloc(VALUE klass);
|
12
|
+
static VALUE create(WrappedType reader, VALUE parent);
|
13
|
+
static void free(WrappedType* p);
|
14
|
+
static WrappedType* unwrap(VALUE self);
|
15
|
+
static VALUE as_struct(VALUE self, VALUE name);
|
16
|
+
|
17
|
+
static VALUE Class;
|
18
|
+
};
|
19
|
+
}
|
20
|
+
|
21
|
+
|
22
|
+
#endif
|
@@ -0,0 +1,171 @@
|
|
1
|
+
#include "ruby_capn_proto.h"
|
2
|
+
#include "dynamic_struct_builder.h"
|
3
|
+
#include "dynamic_struct_reader.h"
|
4
|
+
#include "dynamic_value_reader.h"
|
5
|
+
#include "dynamic_value_builder.h"
|
6
|
+
#include "message_builder.h"
|
7
|
+
#include "malloc_message_builder.h"
|
8
|
+
#include "class_builder.h"
|
9
|
+
#include "exception.h"
|
10
|
+
#include "util.h"
|
11
|
+
|
12
|
+
namespace ruby_capn_proto {
|
13
|
+
using WrappedType = capnp::DynamicStruct::Builder;
|
14
|
+
VALUE DynamicStructBuilder::Class;
|
15
|
+
|
16
|
+
void DynamicStructBuilder::Init() {
|
17
|
+
ClassBuilder("DynamicStructBuilder", rb_cObject).
|
18
|
+
defineAlloc(&alloc).
|
19
|
+
defineMethod("which", &which).
|
20
|
+
defineMethod("write", &write).
|
21
|
+
defineMethod("to_bytes", &to_bytes).
|
22
|
+
defineMethod("[]", &get).
|
23
|
+
defineMethod("[]=", &set).
|
24
|
+
defineMethod("init", (VALUE (*)(int, VALUE*, VALUE))&init).
|
25
|
+
store(&Class);
|
26
|
+
}
|
27
|
+
|
28
|
+
void DynamicStructBuilder::free(WrappedType* p) {
|
29
|
+
p->~Builder();
|
30
|
+
ruby_xfree(p);
|
31
|
+
}
|
32
|
+
|
33
|
+
VALUE DynamicStructBuilder::alloc(VALUE klass) {
|
34
|
+
return Data_Wrap_Struct(klass, NULL, free, ruby_xmalloc(sizeof(WrappedType)));
|
35
|
+
}
|
36
|
+
|
37
|
+
WrappedType* DynamicStructBuilder::unwrap(VALUE self) {
|
38
|
+
WrappedType* p;
|
39
|
+
Data_Get_Struct(self, WrappedType, p);
|
40
|
+
return p;
|
41
|
+
}
|
42
|
+
|
43
|
+
VALUE DynamicStructBuilder::create(WrappedType reader, VALUE parent, bool is_root) {
|
44
|
+
VALUE rb_obj = alloc(Class);
|
45
|
+
WrappedType* wrapped = unwrap(rb_obj);
|
46
|
+
*wrapped = kj::mv(reader);
|
47
|
+
|
48
|
+
rb_iv_set(rb_obj, "parent", parent);
|
49
|
+
rb_iv_set(rb_obj, "is_root", is_root ? Qtrue : Qfalse);
|
50
|
+
|
51
|
+
return rb_obj;
|
52
|
+
}
|
53
|
+
|
54
|
+
VALUE DynamicStructBuilder::init(int argc, VALUE* argv, VALUE self) {
|
55
|
+
VALUE name;
|
56
|
+
VALUE count;
|
57
|
+
|
58
|
+
rb_scan_args(argc, argv, "11", &name, &count);
|
59
|
+
|
60
|
+
try {
|
61
|
+
return _init(self, name, count, argc);
|
62
|
+
} catch (kj::Exception ex) {
|
63
|
+
return Exception::raise(ex);
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
67
|
+
VALUE DynamicStructBuilder::_init(VALUE self, VALUE rb_name, VALUE rb_count, int argc) {
|
68
|
+
auto name = Util::toString(rb_name);
|
69
|
+
|
70
|
+
if (argc == 1) {
|
71
|
+
return DynamicValueBuilder::to_ruby(unwrap(self)->init(name), self);
|
72
|
+
} else {
|
73
|
+
auto count = NUM2ULONG(rb_count);
|
74
|
+
return DynamicValueBuilder::to_ruby(unwrap(self)->init(name, count), self);
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
VALUE DynamicStructBuilder::get(VALUE self, VALUE rb_name) {
|
79
|
+
try {
|
80
|
+
return _get(self, rb_name);
|
81
|
+
} catch (kj::Exception ex) {
|
82
|
+
return Exception::raise(ex);
|
83
|
+
}
|
84
|
+
}
|
85
|
+
|
86
|
+
VALUE DynamicStructBuilder::_get(VALUE self, VALUE rb_name) {
|
87
|
+
auto builder = *unwrap(self);
|
88
|
+
auto name = Util::toString(rb_name);
|
89
|
+
return DynamicValueBuilder::to_ruby(builder.get(name), self);
|
90
|
+
}
|
91
|
+
|
92
|
+
VALUE DynamicStructBuilder::set(VALUE self, VALUE rb_name, VALUE rb_obj) {
|
93
|
+
try {
|
94
|
+
return _set(self, rb_name, rb_obj);
|
95
|
+
} catch (kj::Exception ex) {
|
96
|
+
return Exception::raise(ex);
|
97
|
+
}
|
98
|
+
}
|
99
|
+
|
100
|
+
VALUE DynamicStructBuilder::_set(VALUE self, VALUE rb_field, VALUE rb_obj) {
|
101
|
+
VALUE klass = rb_funcall(rb_obj, rb_intern("class"), 0);
|
102
|
+
auto field = Util::toString(rb_field);
|
103
|
+
|
104
|
+
// TODO: handle assigning lists (see _setDynamicField)
|
105
|
+
if FIXNUM_P(rb_obj) {
|
106
|
+
if (Util::isNegative(rb_obj)) {
|
107
|
+
unwrap(self)->set(field, NUM2LONG(rb_obj));
|
108
|
+
} else {
|
109
|
+
unwrap(self)->set(field, NUM2ULONG(rb_obj));
|
110
|
+
}
|
111
|
+
} else if (RB_TYPE_P(rb_obj, T_FLOAT)) {
|
112
|
+
unwrap(self)->set(field, RFLOAT_VALUE(rb_obj));
|
113
|
+
} else if (rb_obj == Qtrue || rb_obj == Qfalse) {
|
114
|
+
unwrap(self)->set(field, (rb_obj == Qtrue) ? true : false);
|
115
|
+
} else if (RB_TYPE_P(rb_obj, T_STRING)) {
|
116
|
+
// TODO: need to ensure that the UTF8 char buffer is null terminated.
|
117
|
+
// consider something similar to rb_string_value_cstr,
|
118
|
+
// which grows the the buffer if necessary.
|
119
|
+
capnp::DynamicValue::Reader tmp =
|
120
|
+
capnp::Text::Reader(RSTRING_PTR(rb_obj), RSTRING_LEN(rb_obj));
|
121
|
+
unwrap(self)->set(field, tmp);
|
122
|
+
} else if (NIL_P(rb_obj)) {
|
123
|
+
unwrap(self)->set(field, capnp::VOID);
|
124
|
+
} else if (rb_equal(klass, DynamicStructReader::Class)) {
|
125
|
+
unwrap(self)->set(field, *DynamicStructReader::unwrap(rb_obj));
|
126
|
+
} else if (rb_equal(klass, DynamicStructBuilder::Class)) {
|
127
|
+
unwrap(self)->set(field, (*DynamicStructBuilder::unwrap(rb_obj)).asReader());
|
128
|
+
} else {
|
129
|
+
// TODO: raise "Non primitive type"
|
130
|
+
}
|
131
|
+
|
132
|
+
return rb_obj;
|
133
|
+
}
|
134
|
+
|
135
|
+
VALUE DynamicStructBuilder::write(VALUE self, VALUE file) {
|
136
|
+
VALUE rb_fileno = rb_funcall(file, rb_intern("fileno"), 0);
|
137
|
+
int fileno = FIX2INT(rb_fileno);
|
138
|
+
if (!RTEST(rb_iv_get(self, "is_root"))) {
|
139
|
+
rb_raise(Exception::Class, "You can only call write() on the message's root struct.");
|
140
|
+
}
|
141
|
+
|
142
|
+
capnp::MessageBuilder* message_builder = MallocMessageBuilder::unwrap(rb_iv_get(self, "parent"));
|
143
|
+
try {
|
144
|
+
capnp::writeMessageToFd(fileno, message_builder->getSegmentsForOutput());
|
145
|
+
return Qnil;
|
146
|
+
} catch (kj::Exception ex) {
|
147
|
+
return Exception::raise(ex);
|
148
|
+
}
|
149
|
+
}
|
150
|
+
|
151
|
+
VALUE DynamicStructBuilder::to_bytes(VALUE self) {
|
152
|
+
if (!RTEST(rb_iv_get(self, "is_root"))) {
|
153
|
+
rb_raise(Exception::Class, "You can only call to_bytes() on the message's root struct.");
|
154
|
+
}
|
155
|
+
|
156
|
+
capnp::MessageBuilder* message_builder = MallocMessageBuilder::unwrap(rb_iv_get(self, "parent"));
|
157
|
+
auto array = capnp::messageToFlatArray(*message_builder);
|
158
|
+
return rb_str_new((char*)array.begin(), sizeof(capnp::word) * array.size());
|
159
|
+
}
|
160
|
+
|
161
|
+
VALUE DynamicStructBuilder::which(VALUE self) {
|
162
|
+
auto schema_maybe = unwrap(self)->which();
|
163
|
+
KJ_IF_MAYBE(schema, schema_maybe) {
|
164
|
+
auto name = schema->getProto().getName();
|
165
|
+
return rb_str_new(name.begin(), name.size());
|
166
|
+
} else {
|
167
|
+
// throw std::invalid_argument("member was null");
|
168
|
+
return Qnil;
|
169
|
+
}
|
170
|
+
}
|
171
|
+
}
|
@@ -0,0 +1,34 @@
|
|
1
|
+
#ifndef DYNAMIC_STRUCT_BUILDER_H
|
2
|
+
#define DYNAMIC_STRUCT_BUILDER_H
|
3
|
+
|
4
|
+
#include "ruby_capn_proto.h"
|
5
|
+
|
6
|
+
namespace ruby_capn_proto {
|
7
|
+
class DynamicStructBuilder {
|
8
|
+
public:
|
9
|
+
using WrappedType = capnp::DynamicStruct::Builder;
|
10
|
+
static void Init();
|
11
|
+
static VALUE alloc(VALUE klass);
|
12
|
+
static VALUE create(WrappedType reader, VALUE parent, bool is_root);
|
13
|
+
static void free(WrappedType* p);
|
14
|
+
static WrappedType* unwrap(VALUE self);
|
15
|
+
static VALUE which(VALUE self);
|
16
|
+
static VALUE get(VALUE self, VALUE rb_name);
|
17
|
+
static VALUE set(VALUE self, VALUE rb_name, VALUE rb_obj);
|
18
|
+
|
19
|
+
static VALUE init(VALUE self, VALUE rb_name, VALUE rb_obj);
|
20
|
+
static VALUE init(int argc, VALUE* argv, VALUE self);
|
21
|
+
|
22
|
+
static VALUE write(VALUE self, VALUE file);
|
23
|
+
static VALUE to_bytes(VALUE self);
|
24
|
+
|
25
|
+
static VALUE Class;
|
26
|
+
private:
|
27
|
+
static VALUE _get(VALUE self, VALUE name);
|
28
|
+
static VALUE _set(VALUE self, VALUE rb_name, VALUE rb_obj);
|
29
|
+
|
30
|
+
static VALUE _init(VALUE self, VALUE rb_name, VALUE rb_count, int argc);
|
31
|
+
};
|
32
|
+
}
|
33
|
+
|
34
|
+
#endif
|
@@ -2,6 +2,7 @@
|
|
2
2
|
#include "dynamic_struct_reader.h"
|
3
3
|
#include "dynamic_value_reader.h"
|
4
4
|
#include "class_builder.h"
|
5
|
+
#include "exception.h"
|
5
6
|
#include "util.h"
|
6
7
|
|
7
8
|
namespace ruby_capn_proto {
|
@@ -42,9 +43,16 @@ namespace ruby_capn_proto {
|
|
42
43
|
}
|
43
44
|
|
44
45
|
VALUE DynamicStructReader::get(VALUE self, VALUE rb_name) {
|
46
|
+
try {
|
47
|
+
return _get(self, rb_name);
|
48
|
+
} catch (kj::Exception ex) {
|
49
|
+
return Exception::raise(ex);
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
VALUE DynamicStructReader::_get(VALUE self, VALUE rb_name) {
|
45
54
|
auto reader = *unwrap(self);
|
46
55
|
auto name = Util::toString(rb_name);
|
47
|
-
|
48
56
|
return DynamicValueReader::to_ruby(reader.get(name), self);
|
49
57
|
}
|
50
58
|
|
@@ -0,0 +1,53 @@
|
|
1
|
+
#include "ruby_capn_proto.h"
|
2
|
+
#include "dynamic_value_builder.h"
|
3
|
+
#include "dynamic_list_builder.h"
|
4
|
+
#include "dynamic_struct_builder.h"
|
5
|
+
#include "dynamic_object_builder.h"
|
6
|
+
|
7
|
+
namespace ruby_capn_proto {
|
8
|
+
|
9
|
+
VALUE DynamicValueBuilder::to_ruby(capnp::DynamicValue::Builder value, VALUE parent) {
|
10
|
+
switch (value.getType())
|
11
|
+
{
|
12
|
+
case capnp::DynamicValue::BOOL:
|
13
|
+
return value.as<bool>() ? Qtrue : Qfalse;
|
14
|
+
case capnp::DynamicValue::INT:
|
15
|
+
return INT2NUM(value.as<int64_t>());
|
16
|
+
case capnp::DynamicValue::UINT:
|
17
|
+
return UINT2NUM(value.as<uint64_t>());
|
18
|
+
case capnp::DynamicValue::FLOAT:
|
19
|
+
return rb_float_new(value.as<double>());
|
20
|
+
case capnp::DynamicValue::TEXT:
|
21
|
+
{
|
22
|
+
auto text = value.as<capnp::Text>();
|
23
|
+
return rb_str_new(text.begin(), text.size());
|
24
|
+
}
|
25
|
+
case capnp::DynamicValue::DATA:
|
26
|
+
{
|
27
|
+
auto data = value.as<capnp::Data>();
|
28
|
+
return rb_str_new((const char*)data.begin(), data.size());
|
29
|
+
}
|
30
|
+
case capnp::DynamicValue::LIST:
|
31
|
+
return DynamicListBuilder::create(value.as<capnp::DynamicList>(), parent);
|
32
|
+
case capnp::DynamicValue::STRUCT:
|
33
|
+
return DynamicStructBuilder::create(value.as<capnp::DynamicStruct>(), parent, false);
|
34
|
+
case capnp::DynamicValue::ENUM:
|
35
|
+
{
|
36
|
+
auto enumerant_maybe = value.as<capnp::DynamicEnum>().getEnumerant();
|
37
|
+
KJ_IF_MAYBE(enumerant, enumerant_maybe) {
|
38
|
+
auto name = enumerant->getProto().getName();
|
39
|
+
return rb_str_new(name.begin(), name.size());
|
40
|
+
} else {
|
41
|
+
return Qnil;
|
42
|
+
}
|
43
|
+
}
|
44
|
+
case capnp::DynamicValue::OBJECT:
|
45
|
+
return DynamicObjectBuilder::create(value.as<capnp::ObjectPointer>(), parent);
|
46
|
+
case capnp::DynamicValue::VOID:
|
47
|
+
return Qnil;
|
48
|
+
case capnp::DynamicValue::UNKNOWN:
|
49
|
+
default:
|
50
|
+
return Qnil;
|
51
|
+
}
|
52
|
+
}
|
53
|
+
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
#ifndef DYNAMIC_VALUE_BUILDER_H
|
2
|
+
#define DYNAMIC_VALUE_BUILDER_H
|
3
|
+
|
4
|
+
#include "ruby_capn_proto.h"
|
5
|
+
|
6
|
+
namespace ruby_capn_proto {
|
7
|
+
class DynamicValueBuilder {
|
8
|
+
public:
|
9
|
+
static VALUE to_ruby(capnp::DynamicValue::Builder value, VALUE parent);
|
10
|
+
};
|
11
|
+
}
|
12
|
+
|
13
|
+
#endif /* DYNAMIC_VALUE_BUILDER_H */
|
data/ext/capn_proto/exception.cc
CHANGED
@@ -19,6 +19,12 @@ namespace ruby_capn_proto {
|
|
19
19
|
VALUE Exception::create(WrappedType exception) {
|
20
20
|
VALUE msg = Util::toRubyString(exception.getDescription());
|
21
21
|
VALUE rb_exception = rb_funcall(Class, rb_intern("new"), 1, msg);
|
22
|
+
|
22
23
|
return rb_exception;
|
23
24
|
}
|
25
|
+
|
26
|
+
VALUE Exception::raise(WrappedType exception) {
|
27
|
+
rb_exc_raise(create(exception));
|
28
|
+
return Qnil;
|
29
|
+
}
|
24
30
|
}
|
data/ext/capn_proto/exception.h
CHANGED
@@ -8,7 +8,8 @@ namespace ruby_capn_proto {
|
|
8
8
|
public:
|
9
9
|
using WrappedType = kj::Exception;
|
10
10
|
static void Init();
|
11
|
-
static VALUE create(WrappedType
|
11
|
+
static VALUE create(WrappedType exception);
|
12
|
+
static VALUE raise(WrappedType exception);
|
12
13
|
|
13
14
|
static VALUE Class;
|
14
15
|
};
|
@@ -0,0 +1,61 @@
|
|
1
|
+
#include "ruby_capn_proto.h"
|
2
|
+
#include "message_reader.h"
|
3
|
+
#include "flat_array_message_reader.h"
|
4
|
+
#include "struct_schema.h"
|
5
|
+
#include "dynamic_struct_reader.h"
|
6
|
+
#include "class_builder.h"
|
7
|
+
#include "exception.h"
|
8
|
+
|
9
|
+
namespace ruby_capn_proto {
|
10
|
+
using WrappedType = capnp::FlatArrayMessageReader;
|
11
|
+
VALUE FlatArrayMessageReader::Class;
|
12
|
+
|
13
|
+
void FlatArrayMessageReader::Init() {
|
14
|
+
ClassBuilder("FlatArrayMessageReader", MessageReader::Class).
|
15
|
+
defineAlloc(&alloc).
|
16
|
+
defineMethod("initialize", &initialize).
|
17
|
+
defineMethod("get_root", &get_root).
|
18
|
+
store(&Class);
|
19
|
+
}
|
20
|
+
|
21
|
+
VALUE FlatArrayMessageReader::alloc(VALUE klass) {
|
22
|
+
return Data_Wrap_Struct(klass, NULL, free, ruby_xmalloc(sizeof(WrappedType)));
|
23
|
+
}
|
24
|
+
|
25
|
+
VALUE FlatArrayMessageReader::initialize(VALUE self, VALUE rb_buff) {
|
26
|
+
rb_iv_set(self, "buff", rb_buff);
|
27
|
+
auto str = RSTRING_PTR(rb_buff);
|
28
|
+
auto len = RSTRING_LEN(rb_buff);
|
29
|
+
kj::ArrayPtr<const capnp::word> buff((const capnp::word*)str, len/sizeof(capnp::word));
|
30
|
+
|
31
|
+
try {
|
32
|
+
WrappedType* p = unwrap(self);
|
33
|
+
new (p) WrappedType(buff);
|
34
|
+
} catch (kj::Exception ex) {
|
35
|
+
return Exception::raise(ex);
|
36
|
+
}
|
37
|
+
|
38
|
+
return Qnil;
|
39
|
+
}
|
40
|
+
|
41
|
+
void FlatArrayMessageReader::free(WrappedType* p) {
|
42
|
+
p->~FlatArrayMessageReader();
|
43
|
+
ruby_xfree(p);
|
44
|
+
}
|
45
|
+
|
46
|
+
WrappedType* FlatArrayMessageReader::unwrap(VALUE self) {
|
47
|
+
WrappedType* p;
|
48
|
+
Data_Get_Struct(self, WrappedType, p);
|
49
|
+
return p;
|
50
|
+
}
|
51
|
+
|
52
|
+
VALUE FlatArrayMessageReader::get_root(VALUE self, VALUE rb_schema) {
|
53
|
+
if (rb_respond_to(rb_schema, rb_intern("schema"))) {
|
54
|
+
rb_schema = rb_funcall(rb_schema, rb_intern("schema"), 0);
|
55
|
+
}
|
56
|
+
|
57
|
+
auto schema = *StructSchema::unwrap(rb_schema);
|
58
|
+
auto reader = unwrap(self)->getRoot<capnp::DynamicStruct>(schema);
|
59
|
+
return DynamicStructReader::create(reader, self);
|
60
|
+
}
|
61
|
+
}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
#ifndef FLAT_ARRAY_MESSAGE_READER_H
|
2
|
+
#define FLAT_ARRAY_MESSAGE_READER_H
|
3
|
+
|
4
|
+
#include "ruby_capn_proto.h"
|
5
|
+
|
6
|
+
namespace ruby_capn_proto {
|
7
|
+
class FlatArrayMessageReader {
|
8
|
+
public:
|
9
|
+
using WrappedType = capnp::FlatArrayMessageReader;
|
10
|
+
static void Init();
|
11
|
+
static VALUE alloc(VALUE klass);
|
12
|
+
static VALUE initialize(VALUE klass, VALUE io);
|
13
|
+
static void free(WrappedType* p);
|
14
|
+
static WrappedType* unwrap(VALUE self);
|
15
|
+
static VALUE get_root(VALUE self, VALUE schema);
|
16
|
+
|
17
|
+
static VALUE Class;
|
18
|
+
};
|
19
|
+
}
|
20
|
+
|
21
|
+
#endif /* FLAT_ARRAY_MESSAGE_READER_H */
|
data/ext/capn_proto/init.cc
CHANGED
@@ -1,36 +1,53 @@
|
|
1
1
|
#include "ruby_capn_proto.h"
|
2
|
-
|
2
|
+
|
3
|
+
#include "exception.h"
|
4
|
+
|
3
5
|
#include "schema_parser.h"
|
4
|
-
#include "
|
6
|
+
#include "parsed_schema.h"
|
5
7
|
#include "struct_schema.h"
|
8
|
+
#include "schema_node_reader.h"
|
6
9
|
#include "nested_node_reader.h"
|
7
10
|
#include "list_nested_node_reader.h"
|
11
|
+
#include "field_list.h"
|
12
|
+
|
13
|
+
#include "message_reader.h"
|
14
|
+
#include "message_builder.h"
|
15
|
+
#include "stream_fd_message_reader.h"
|
16
|
+
#include "malloc_message_builder.h"
|
17
|
+
#include "flat_array_message_reader.h"
|
18
|
+
|
8
19
|
#include "dynamic_struct_reader.h"
|
20
|
+
#include "dynamic_struct_builder.h"
|
9
21
|
#include "dynamic_list_reader.h"
|
10
|
-
#include "
|
22
|
+
#include "dynamic_list_builder.h"
|
11
23
|
#include "dynamic_object_reader.h"
|
12
|
-
#include "
|
13
|
-
#include "field_list.h"
|
14
|
-
|
15
|
-
extern "C" {
|
16
|
-
void Init_init();
|
17
|
-
}
|
24
|
+
#include "dynamic_object_builder.h"
|
18
25
|
|
19
26
|
using namespace ruby_capn_proto;
|
20
27
|
|
21
28
|
extern "C" {
|
22
29
|
void Init_capn_proto() {
|
30
|
+
Exception::Init();
|
31
|
+
|
23
32
|
SchemaParser::Init();
|
24
|
-
SchemaNodeReader::Init();
|
25
33
|
ParsedSchema::Init();
|
26
34
|
StructSchema::Init();
|
27
|
-
|
28
|
-
ListNestedNodeReader::Init();
|
35
|
+
SchemaNodeReader::Init();
|
29
36
|
NestedNodeReader::Init();
|
37
|
+
ListNestedNodeReader::Init();
|
38
|
+
FieldList::Init();
|
39
|
+
|
40
|
+
MessageReader::Init();
|
41
|
+
MessageBuilder::Init();
|
42
|
+
StreamFdMessageReader::Init();
|
43
|
+
MallocMessageBuilder::Init();
|
44
|
+
FlatArrayMessageReader::Init();
|
45
|
+
|
30
46
|
DynamicStructReader::Init();
|
47
|
+
DynamicStructBuilder::Init();
|
31
48
|
DynamicListReader::Init();
|
32
|
-
|
33
|
-
FieldList::Init();
|
49
|
+
DynamicListBuilder::Init();
|
34
50
|
DynamicObjectReader::Init();
|
51
|
+
DynamicObjectBuilder::Init();
|
35
52
|
}
|
36
53
|
}
|
@@ -0,0 +1,51 @@
|
|
1
|
+
#include "ruby_capn_proto.h"
|
2
|
+
#include "malloc_message_builder.h"
|
3
|
+
#include "message_builder.h"
|
4
|
+
#include "struct_schema.h"
|
5
|
+
#include "dynamic_struct_builder.h"
|
6
|
+
#include "class_builder.h"
|
7
|
+
|
8
|
+
namespace ruby_capn_proto {
|
9
|
+
using WrappedType = capnp::MallocMessageBuilder;
|
10
|
+
VALUE MallocMessageBuilder::Class;
|
11
|
+
|
12
|
+
void MallocMessageBuilder::Init() {
|
13
|
+
ClassBuilder("MallocMessageBuilder", MessageBuilder::Class).
|
14
|
+
defineAlloc(&alloc).
|
15
|
+
defineMethod("initialize", &initialize).
|
16
|
+
defineMethod("init_root", &init_root).
|
17
|
+
// defineMethod("get_root", &get_root).
|
18
|
+
store(&Class);
|
19
|
+
}
|
20
|
+
|
21
|
+
VALUE MallocMessageBuilder::alloc(VALUE klass) {
|
22
|
+
return Data_Wrap_Struct(klass, NULL, free, ruby_xmalloc(sizeof(WrappedType)));
|
23
|
+
}
|
24
|
+
|
25
|
+
VALUE MallocMessageBuilder::initialize(VALUE self) {
|
26
|
+
WrappedType* p = unwrap(self);
|
27
|
+
new (p) WrappedType();
|
28
|
+
return Qnil;
|
29
|
+
}
|
30
|
+
|
31
|
+
void MallocMessageBuilder::free(WrappedType* p) {
|
32
|
+
p->~MallocMessageBuilder();
|
33
|
+
ruby_xfree(p);
|
34
|
+
}
|
35
|
+
|
36
|
+
WrappedType* MallocMessageBuilder::unwrap(VALUE self) {
|
37
|
+
WrappedType* p;
|
38
|
+
Data_Get_Struct(self, WrappedType, p);
|
39
|
+
return p;
|
40
|
+
}
|
41
|
+
|
42
|
+
VALUE MallocMessageBuilder::init_root(VALUE self, VALUE rb_schema) {
|
43
|
+
if (rb_respond_to(rb_schema, rb_intern("schema"))) {
|
44
|
+
rb_schema = rb_funcall(rb_schema, rb_intern("schema"), 0);
|
45
|
+
}
|
46
|
+
|
47
|
+
auto schema = *StructSchema::unwrap(rb_schema);
|
48
|
+
auto builder = unwrap(self)->initRoot<capnp::DynamicStruct>(schema);
|
49
|
+
return DynamicStructBuilder::create(builder, self, true);
|
50
|
+
}
|
51
|
+
}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
#ifndef MALLOC_MESSAGE_BUILDER_H
|
2
|
+
#define MALLOC_MESSAGE_BUILDER_H
|
3
|
+
|
4
|
+
#include "ruby_capn_proto.h"
|
5
|
+
|
6
|
+
namespace ruby_capn_proto {
|
7
|
+
class MallocMessageBuilder {
|
8
|
+
public:
|
9
|
+
using WrappedType = capnp::MallocMessageBuilder;
|
10
|
+
static void Init();
|
11
|
+
static VALUE alloc(VALUE klass);
|
12
|
+
static VALUE initialize(VALUE klass);
|
13
|
+
static void free(WrappedType* p);
|
14
|
+
static WrappedType* unwrap(VALUE self);
|
15
|
+
static VALUE init_root(VALUE name, VALUE schema);
|
16
|
+
|
17
|
+
static VALUE Class;
|
18
|
+
};
|
19
|
+
}
|
20
|
+
|
21
|
+
#endif
|
@@ -0,0 +1,22 @@
|
|
1
|
+
#include "ruby_capn_proto.h"
|
2
|
+
#include "message_builder.h"
|
3
|
+
#include "class_builder.h"
|
4
|
+
#include "struct_schema.h"
|
5
|
+
#include "dynamic_struct_reader.h"
|
6
|
+
#include "util.h"
|
7
|
+
|
8
|
+
namespace ruby_capn_proto {
|
9
|
+
using WrappedType = capnp::MessageBuilder;
|
10
|
+
VALUE MessageBuilder::Class;
|
11
|
+
|
12
|
+
void MessageBuilder::Init() {
|
13
|
+
ClassBuilder("MessageBuilder", rb_cObject).
|
14
|
+
store(&Class);
|
15
|
+
}
|
16
|
+
|
17
|
+
WrappedType* MessageBuilder::unwrap(VALUE self) {
|
18
|
+
WrappedType* p;
|
19
|
+
Data_Get_Struct(self, WrappedType, p);
|
20
|
+
return p;
|
21
|
+
}
|
22
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#ifndef MESSAGE_BUILDER_H
|
2
|
+
#define MESSAGE_BUILDER_H
|
3
|
+
|
4
|
+
#include "ruby_capn_proto.h"
|
5
|
+
|
6
|
+
namespace ruby_capn_proto {
|
7
|
+
class MessageBuilder {
|
8
|
+
public:
|
9
|
+
using WrappedType = capnp::MessageBuilder;
|
10
|
+
static void Init();
|
11
|
+
static WrappedType* unwrap(VALUE self);
|
12
|
+
|
13
|
+
static VALUE Class;
|
14
|
+
};
|
15
|
+
}
|
16
|
+
|
17
|
+
#endif /* MESSAGE_BUILDER_H */
|
@@ -4,6 +4,7 @@
|
|
4
4
|
#include "struct_schema.h"
|
5
5
|
#include "dynamic_struct_reader.h"
|
6
6
|
#include "class_builder.h"
|
7
|
+
#include "exception.h"
|
7
8
|
|
8
9
|
namespace ruby_capn_proto {
|
9
10
|
using WrappedType = capnp::StreamFdMessageReader;
|
@@ -25,7 +26,12 @@ namespace ruby_capn_proto {
|
|
25
26
|
VALUE rb_fileno = rb_funcall(rb_io, rb_intern("fileno"), 0);
|
26
27
|
auto fileno = FIX2INT(rb_fileno);
|
27
28
|
WrappedType* p = unwrap(self);
|
28
|
-
|
29
|
+
|
30
|
+
try {
|
31
|
+
new (p) WrappedType(fileno);
|
32
|
+
} catch (kj::Exception ex) {
|
33
|
+
return Exception::raise(ex);
|
34
|
+
}
|
29
35
|
|
30
36
|
return Qnil;
|
31
37
|
}
|
@@ -12,7 +12,7 @@ namespace ruby_capn_proto {
|
|
12
12
|
static VALUE initialize(VALUE klass, VALUE io);
|
13
13
|
static void free(WrappedType* p);
|
14
14
|
static WrappedType* unwrap(VALUE self);
|
15
|
-
static VALUE get_root(VALUE
|
15
|
+
static VALUE get_root(VALUE self, VALUE schema);
|
16
16
|
|
17
17
|
static VALUE Class;
|
18
18
|
};
|
data/ext/capn_proto/util.cc
CHANGED
@@ -22,4 +22,9 @@ namespace ruby_capn_proto {
|
|
22
22
|
VALUE Util::toRubyString(kj::StringPtr string) {
|
23
23
|
return rb_str_new(string.begin(), string.size());
|
24
24
|
}
|
25
|
+
|
26
|
+
bool Util::isNegative(VALUE rb_obj) {
|
27
|
+
if (FIXNUM_P(rb_obj)) return FIX2LONG(rb_obj) < 0;
|
28
|
+
return RTEST(rb_funcall(rb_obj, '<', 1, INT2FIX(0)));
|
29
|
+
}
|
25
30
|
}
|
data/ext/capn_proto/util.h
CHANGED
data/lib/capn_proto/version.rb
CHANGED
data/lib/capn_proto.rb
CHANGED
@@ -22,9 +22,55 @@ module CapnProto
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
+
DynamicListBuilder.class_eval do
|
26
|
+
include Enumerable
|
27
|
+
def each
|
28
|
+
return to_enum(:each) unless block_given?
|
29
|
+
(0...size).each do |n|
|
30
|
+
yield self[n]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
25
35
|
DynamicStructReader.class_eval do
|
36
|
+
# examples:
|
37
|
+
#
|
38
|
+
# x.employed?
|
39
|
+
# x.age
|
26
40
|
def method_missing(name, *args, &block)
|
27
|
-
|
41
|
+
name = name.to_s
|
42
|
+
|
43
|
+
if name.end_with?("?")
|
44
|
+
which == name[0..-2]
|
45
|
+
else
|
46
|
+
self[name]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
DynamicStructBuilder.class_eval do
|
52
|
+
# examples:
|
53
|
+
#
|
54
|
+
# x.initSandwich
|
55
|
+
# x.initPeople(10)
|
56
|
+
# x.employed?
|
57
|
+
# x.age = 10
|
58
|
+
# x.age
|
59
|
+
def method_missing(name, *args, &block)
|
60
|
+
name = name.to_s
|
61
|
+
|
62
|
+
if name.start_with?("init") && name.size > 4
|
63
|
+
name = name[4..-1]
|
64
|
+
name[0] = name[0].downcase
|
65
|
+
init(name, *args)
|
66
|
+
elsif name.end_with?("=")
|
67
|
+
name = name[0..-2]
|
68
|
+
self[name] = args[0]
|
69
|
+
elsif name.end_with?("?")
|
70
|
+
which == name[0..-2]
|
71
|
+
else
|
72
|
+
self[name]
|
73
|
+
end
|
28
74
|
end
|
29
75
|
end
|
30
76
|
|
@@ -73,11 +119,18 @@ module CapnProto
|
|
73
119
|
reader.get_root(self)
|
74
120
|
end
|
75
121
|
|
76
|
-
def
|
77
|
-
|
122
|
+
def make_from_bytes(bytes)
|
123
|
+
# TODO: support FFI pointers
|
124
|
+
reader = FlatArrayMessageReader.new(bytes)
|
125
|
+
reader.get_root(self)
|
78
126
|
end
|
79
127
|
|
80
|
-
def new_message
|
128
|
+
def new_message
|
129
|
+
builder = MallocMessageBuilder.new
|
130
|
+
builder.init_root(self)
|
131
|
+
end
|
132
|
+
|
133
|
+
def read_packed_from(io)
|
81
134
|
raise 'not implemented'
|
82
135
|
end
|
83
136
|
end
|
data/spec/capn_proto_spec.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
require 'spec_helper'
|
1
3
|
require 'capn_proto'
|
2
4
|
|
3
5
|
ADDRESSBOOK_SCHEMA = File.expand_path("../addressbook.capnp", __FILE__)
|
@@ -5,3 +7,74 @@ ADDRESSBOOK_SCHEMA = File.expand_path("../addressbook.capnp", __FILE__)
|
|
5
7
|
module AddressBook extend CapnProto::SchemaLoader
|
6
8
|
load_schema(ADDRESSBOOK_SCHEMA)
|
7
9
|
end
|
10
|
+
|
11
|
+
describe "reading" do
|
12
|
+
describe "Dynamic Structs" do
|
13
|
+
let(:file) { open_file("addressbook.bin") }
|
14
|
+
let(:addresses) { AddressBook::AddressBook.read_from(file) }
|
15
|
+
|
16
|
+
it "unkown fields raise exception" do
|
17
|
+
expect { addresses.foo }.to raise_error(CapnProto::Exception)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "Dynamic Lists" do
|
22
|
+
let(:file) { open_file("addressbook.bin") }
|
23
|
+
let(:addresses) { AddressBook::AddressBook.read_from(file) }
|
24
|
+
let(:people) { addresses.people }
|
25
|
+
|
26
|
+
it "#[] given out-of-bounds index raises" do
|
27
|
+
expect { addresses.people[999999] }.to raise_error(CapnProto::Exception)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "writing" do
|
33
|
+
describe "#write" do
|
34
|
+
it "full circle" do
|
35
|
+
tmp = Tempfile.new('test.bin')
|
36
|
+
addresses = AddressBook::AddressBook.new_message
|
37
|
+
people = addresses.initPeople(1)
|
38
|
+
bob = people[0]
|
39
|
+
bob.name = "Bob"
|
40
|
+
bob.id = 123
|
41
|
+
addresses.write(tmp)
|
42
|
+
|
43
|
+
tmp.rewind
|
44
|
+
addresses = AddressBook::AddressBook.read_from(tmp)
|
45
|
+
expect(addresses.people.size).to eq 1
|
46
|
+
expect(addresses.people.first.name).to eq "Bob"
|
47
|
+
expect(addresses.people.first.id).to eq 123
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "#to_bytes" do
|
52
|
+
it "full circle" do
|
53
|
+
addresses = AddressBook::AddressBook.new_message
|
54
|
+
people = addresses.initPeople(1)
|
55
|
+
bob = people[0]
|
56
|
+
bob.name = "Bob"
|
57
|
+
bob.id = 123
|
58
|
+
bytes = addresses.to_bytes
|
59
|
+
|
60
|
+
addresses = AddressBook::AddressBook.make_from_bytes(bytes)
|
61
|
+
expect(addresses.people.size).to eq 1
|
62
|
+
expect(addresses.people.first.name).to eq "Bob"
|
63
|
+
expect(addresses.people.first.id).to eq 123
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "Dynamic Structs" do
|
68
|
+
let(:addresses) { AddressBook::AddressBook.new_message }
|
69
|
+
|
70
|
+
it "works" do
|
71
|
+
people = addresses.initPeople(3)
|
72
|
+
bob = people.first
|
73
|
+
bob.name = "Bob"
|
74
|
+
bob.id = 10
|
75
|
+
|
76
|
+
people[1] = bob
|
77
|
+
x = people[1]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: capn_proto
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.1.alpha.
|
4
|
+
version: 0.0.1.alpha.5
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-09-
|
12
|
+
date: 2013-09-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -114,16 +114,23 @@ files:
|
|
114
114
|
- examples/create_test_data.py
|
115
115
|
- examples/example.rb
|
116
116
|
- ext/capn_proto/.ycm_extra_conf.py
|
117
|
-
- ext/capn_proto/.ycm_extra_conf.pyc
|
118
117
|
- ext/capn_proto/class_builder.cc
|
119
118
|
- ext/capn_proto/class_builder.h
|
120
119
|
- ext/capn_proto/cxx_compiler.rb
|
120
|
+
- ext/capn_proto/dynamic_list_builder.cc
|
121
|
+
- ext/capn_proto/dynamic_list_builder.h
|
121
122
|
- ext/capn_proto/dynamic_list_reader.cc
|
122
123
|
- ext/capn_proto/dynamic_list_reader.h
|
124
|
+
- ext/capn_proto/dynamic_object_builder.cc
|
125
|
+
- ext/capn_proto/dynamic_object_builder.h
|
123
126
|
- ext/capn_proto/dynamic_object_reader.cc
|
124
127
|
- ext/capn_proto/dynamic_object_reader.h
|
128
|
+
- ext/capn_proto/dynamic_struct_builder.cc
|
129
|
+
- ext/capn_proto/dynamic_struct_builder.h
|
125
130
|
- ext/capn_proto/dynamic_struct_reader.cc
|
126
131
|
- ext/capn_proto/dynamic_struct_reader.h
|
132
|
+
- ext/capn_proto/dynamic_value_builder.cc
|
133
|
+
- ext/capn_proto/dynamic_value_builder.h
|
127
134
|
- ext/capn_proto/dynamic_value_reader.cc
|
128
135
|
- ext/capn_proto/dynamic_value_reader.h
|
129
136
|
- ext/capn_proto/exception.cc
|
@@ -131,9 +138,15 @@ files:
|
|
131
138
|
- ext/capn_proto/extconf.rb
|
132
139
|
- ext/capn_proto/field_list.cc
|
133
140
|
- ext/capn_proto/field_list.h
|
141
|
+
- ext/capn_proto/flat_array_message_reader.cc
|
142
|
+
- ext/capn_proto/flat_array_message_reader.h
|
134
143
|
- ext/capn_proto/init.cc
|
135
144
|
- ext/capn_proto/list_nested_node_reader.cc
|
136
145
|
- ext/capn_proto/list_nested_node_reader.h
|
146
|
+
- ext/capn_proto/malloc_message_builder.cc
|
147
|
+
- ext/capn_proto/malloc_message_builder.h
|
148
|
+
- ext/capn_proto/message_builder.cc
|
149
|
+
- ext/capn_proto/message_builder.h
|
137
150
|
- ext/capn_proto/message_reader.cc
|
138
151
|
- ext/capn_proto/message_reader.h
|
139
152
|
- ext/capn_proto/nested_node_reader.cc
|
@@ -162,6 +175,7 @@ files:
|
|
162
175
|
- spec/addressbook.capnp
|
163
176
|
- spec/capn_proto_spec.rb
|
164
177
|
- spec/create_test_data.py
|
178
|
+
- spec/spec_helper.rb
|
165
179
|
homepage: https://github.com/cstrahan/capnp-ruby
|
166
180
|
licenses:
|
167
181
|
- MIT
|
@@ -177,7 +191,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
177
191
|
version: '0'
|
178
192
|
segments:
|
179
193
|
- 0
|
180
|
-
hash:
|
194
|
+
hash: 3271871129015226386
|
181
195
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
182
196
|
none: false
|
183
197
|
requirements:
|
Binary file
|