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.
Files changed (35) hide show
  1. data/.gitignore +1 -0
  2. data/README.md +48 -11
  3. data/Rakefile +1 -0
  4. data/ext/capn_proto/dynamic_list_builder.cc +123 -0
  5. data/ext/capn_proto/dynamic_list_builder.h +27 -0
  6. data/ext/capn_proto/dynamic_list_reader.cc +9 -0
  7. data/ext/capn_proto/dynamic_list_reader.h +2 -0
  8. data/ext/capn_proto/dynamic_object_builder.cc +57 -0
  9. data/ext/capn_proto/dynamic_object_builder.h +22 -0
  10. data/ext/capn_proto/dynamic_object_reader.h +1 -1
  11. data/ext/capn_proto/dynamic_struct_builder.cc +171 -0
  12. data/ext/capn_proto/dynamic_struct_builder.h +34 -0
  13. data/ext/capn_proto/dynamic_struct_reader.cc +9 -1
  14. data/ext/capn_proto/dynamic_struct_reader.h +2 -0
  15. data/ext/capn_proto/dynamic_value_builder.cc +53 -0
  16. data/ext/capn_proto/dynamic_value_builder.h +13 -0
  17. data/ext/capn_proto/exception.cc +6 -0
  18. data/ext/capn_proto/exception.h +2 -1
  19. data/ext/capn_proto/flat_array_message_reader.cc +61 -0
  20. data/ext/capn_proto/flat_array_message_reader.h +21 -0
  21. data/ext/capn_proto/init.cc +31 -14
  22. data/ext/capn_proto/malloc_message_builder.cc +51 -0
  23. data/ext/capn_proto/malloc_message_builder.h +21 -0
  24. data/ext/capn_proto/message_builder.cc +22 -0
  25. data/ext/capn_proto/message_builder.h +17 -0
  26. data/ext/capn_proto/stream_fd_message_reader.cc +7 -1
  27. data/ext/capn_proto/stream_fd_message_reader.h +1 -1
  28. data/ext/capn_proto/util.cc +5 -0
  29. data/ext/capn_proto/util.h +1 -0
  30. data/lib/capn_proto/version.rb +1 -1
  31. data/lib/capn_proto.rb +57 -4
  32. data/spec/capn_proto_spec.rb +73 -0
  33. data/spec/spec_helper.rb +8 -0
  34. metadata +18 -4
  35. data/ext/capn_proto/.ycm_extra_conf.pyc +0 -0
data/.gitignore CHANGED
@@ -1,5 +1,6 @@
1
1
  Gemfile.lock
2
2
  *.bundle
3
+ *.pyc
3
4
  tmp
4
5
  .env
5
6
  pkg
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
- which = person.employment.which
45
-
46
- if which == "unemployed"
71
+ if person.employment.unemployed?
47
72
  puts "unemployed"
48
- elsif which == 'employer'
73
+ if person.employment.employer?
49
74
  puts "employer: #{person.employment.employer}"
50
- elsif which == "school"
75
+ if person.employment.school?
51
76
  puts "student at: #{person.employment.school}"
52
- elsif which == "selfEmployed"
77
+ if person.employment.selfEmployed?
53
78
  puts "self employed"
54
79
  end
55
80
  end
56
81
  end
57
82
 
58
- file = File.open("addressbook.bin", "rb")
59
- print_address_book(file)
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
- What's to come:
97
+ - From byte string
98
+ - From file descriptor
69
99
  - Message writing
100
+ - To byte string
101
+ - To file descriptor
70
102
 
71
- Proper support for [JRuby][jruby] will come after I implement support for Java.
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
@@ -21,6 +21,7 @@ task :default => [:compile, :spec]
21
21
  Rake::Task["clean"].clear
22
22
  task :clean do
23
23
  rm_r "tmp" rescue nil
24
+ rm_r "pkg" rescue nil
24
25
  rm "lib/capn_proto/capn_proto.bundle" rescue nil
25
26
  end
26
27
 
@@ -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();
@@ -17,6 +17,8 @@ namespace ruby_capn_proto {
17
17
  static VALUE size(VALUE self);
18
18
 
19
19
  static VALUE Class;
20
+ private:
21
+ static VALUE _get(VALUE self, VALUE index);
20
22
  };
21
23
  }
22
24
 
@@ -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
@@ -19,4 +19,4 @@ namespace ruby_capn_proto {
19
19
  }
20
20
 
21
21
 
22
- #endif /* DYNAMIC_STRUCT_READER_H */
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
 
@@ -16,6 +16,8 @@ namespace ruby_capn_proto {
16
16
  static VALUE get(VALUE self, VALUE name);
17
17
 
18
18
  static VALUE Class;
19
+ private:
20
+ static VALUE _get(VALUE self, VALUE name);
19
21
  };
20
22
  }
21
23
 
@@ -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 */
@@ -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
  }
@@ -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 schema);
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 */
@@ -1,36 +1,53 @@
1
1
  #include "ruby_capn_proto.h"
2
- #include "parsed_schema.h"
2
+
3
+ #include "exception.h"
4
+
3
5
  #include "schema_parser.h"
4
- #include "schema_node_reader.h"
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 "stream_fd_message_reader.h"
22
+ #include "dynamic_list_builder.h"
11
23
  #include "dynamic_object_reader.h"
12
- #include "message_reader.h"
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
- MessageReader::Init();
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
- StreamFdMessageReader::Init();
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
- new (p) WrappedType(fileno);
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 name, VALUE schema);
15
+ static VALUE get_root(VALUE self, VALUE schema);
16
16
 
17
17
  static VALUE Class;
18
18
  };
@@ -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
  }
@@ -8,6 +8,7 @@ namespace ruby_capn_proto {
8
8
  public:
9
9
  static kj::Array<kj::String> toStringArray(VALUE array_of_strings);
10
10
  static kj::String toString(VALUE string);
11
+ static bool isNegative(VALUE rb_obj);
11
12
 
12
13
  static VALUE toRubyString(kj::StringPtr string);
13
14
  };
@@ -1,3 +1,3 @@
1
1
  module CapnProto
2
- VERSION = "0.0.1.alpha.4"
2
+ VERSION = "0.0.1.alpha.5"
3
3
  end
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
- self[name.to_s, *args, &block]
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 read_packed_from(io)
77
- raise 'not implemented'
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(file)
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
@@ -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
@@ -0,0 +1,8 @@
1
+ RSpec.configure do |c|
2
+ c.include(Module.new do
3
+ def open_file(path)
4
+ path = File.join(File.expand_path("../", __FILE__), path)
5
+ File.open(path, "rb")
6
+ end
7
+ end)
8
+ end
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
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-25 00:00:00.000000000 Z
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: -525111796228691179
194
+ hash: 3271871129015226386
181
195
  required_rubygems_version: !ruby/object:Gem::Requirement
182
196
  none: false
183
197
  requirements:
Binary file