capn_proto 0.0.1.alpha.4 → 0.0.1.alpha.5
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.
- 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
|