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.
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