capn_proto-rpc 0.1.1.alpha.rpc

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.travis.yml +19 -0
  4. data/Gemfile +2 -0
  5. data/LICENSE +19 -0
  6. data/README.md +249 -0
  7. data/Rakefile +44 -0
  8. data/capn_proto.gemspec +37 -0
  9. data/examples/addressbook.bin +0 -0
  10. data/examples/addressbook.capnp +31 -0
  11. data/examples/create_test_data.py +39 -0
  12. data/examples/example.rb +38 -0
  13. data/ext/capn_proto/.ycm_extra_conf.py +65 -0
  14. data/ext/capn_proto/EzRpc_client.cc +52 -0
  15. data/ext/capn_proto/EzRpc_client.h +21 -0
  16. data/ext/capn_proto/EzRpc_server.cc +79 -0
  17. data/ext/capn_proto/EzRpc_server.h +32 -0
  18. data/ext/capn_proto/call_context.cc +67 -0
  19. data/ext/capn_proto/call_context.h +25 -0
  20. data/ext/capn_proto/capability_client.cc +47 -0
  21. data/ext/capn_proto/capability_client.h +21 -0
  22. data/ext/capn_proto/class_builder.cc +80 -0
  23. data/ext/capn_proto/class_builder.h +72 -0
  24. data/ext/capn_proto/cxx_compiler.rb +126 -0
  25. data/ext/capn_proto/dynamic_capability_client.cc +73 -0
  26. data/ext/capn_proto/dynamic_capability_client.h +22 -0
  27. data/ext/capn_proto/dynamic_list_builder.cc +123 -0
  28. data/ext/capn_proto/dynamic_list_builder.h +27 -0
  29. data/ext/capn_proto/dynamic_list_reader.cc +63 -0
  30. data/ext/capn_proto/dynamic_list_reader.h +25 -0
  31. data/ext/capn_proto/dynamic_object_builder.cc +57 -0
  32. data/ext/capn_proto/dynamic_object_builder.h +22 -0
  33. data/ext/capn_proto/dynamic_object_reader.cc +56 -0
  34. data/ext/capn_proto/dynamic_object_reader.h +22 -0
  35. data/ext/capn_proto/dynamic_struct_builder.cc +180 -0
  36. data/ext/capn_proto/dynamic_struct_builder.h +34 -0
  37. data/ext/capn_proto/dynamic_struct_reader.cc +69 -0
  38. data/ext/capn_proto/dynamic_struct_reader.h +25 -0
  39. data/ext/capn_proto/dynamic_value_builder.cc +53 -0
  40. data/ext/capn_proto/dynamic_value_builder.h +13 -0
  41. data/ext/capn_proto/dynamic_value_reader.cc +55 -0
  42. data/ext/capn_proto/dynamic_value_reader.h +13 -0
  43. data/ext/capn_proto/exception.cc +34 -0
  44. data/ext/capn_proto/exception.h +20 -0
  45. data/ext/capn_proto/extconf.rb +32 -0
  46. data/ext/capn_proto/field_list.cc +51 -0
  47. data/ext/capn_proto/field_list.h +23 -0
  48. data/ext/capn_proto/flat_array_message_reader.cc +61 -0
  49. data/ext/capn_proto/flat_array_message_reader.h +21 -0
  50. data/ext/capn_proto/init.cc +71 -0
  51. data/ext/capn_proto/interface_method.cc +38 -0
  52. data/ext/capn_proto/interface_method.h +21 -0
  53. data/ext/capn_proto/interface_schema.cc +51 -0
  54. data/ext/capn_proto/interface_schema.h +26 -0
  55. data/ext/capn_proto/list_nested_node_reader.cc +53 -0
  56. data/ext/capn_proto/list_nested_node_reader.h +24 -0
  57. data/ext/capn_proto/malloc_message_builder.cc +51 -0
  58. data/ext/capn_proto/malloc_message_builder.h +21 -0
  59. data/ext/capn_proto/message_builder.cc +22 -0
  60. data/ext/capn_proto/message_builder.h +17 -0
  61. data/ext/capn_proto/message_reader.cc +30 -0
  62. data/ext/capn_proto/message_reader.h +17 -0
  63. data/ext/capn_proto/nested_node_reader.cc +42 -0
  64. data/ext/capn_proto/nested_node_reader.h +21 -0
  65. data/ext/capn_proto/parsed_schema.cc +65 -0
  66. data/ext/capn_proto/parsed_schema.h +24 -0
  67. data/ext/capn_proto/rb.cc +0 -0
  68. data/ext/capn_proto/rb.h +0 -0
  69. data/ext/capn_proto/remote_promise.cc +116 -0
  70. data/ext/capn_proto/remote_promise.h +30 -0
  71. data/ext/capn_proto/ruby_capability_server.cc +23 -0
  72. data/ext/capn_proto/ruby_capability_server.h +21 -0
  73. data/ext/capn_proto/ruby_capn_proto.cc +4 -0
  74. data/ext/capn_proto/ruby_capn_proto.h +42 -0
  75. data/ext/capn_proto/schema_node_reader.cc +59 -0
  76. data/ext/capn_proto/schema_node_reader.h +23 -0
  77. data/ext/capn_proto/schema_parser.cc +61 -0
  78. data/ext/capn_proto/schema_parser.h +20 -0
  79. data/ext/capn_proto/stream_fd_message_reader.cc +59 -0
  80. data/ext/capn_proto/stream_fd_message_reader.h +21 -0
  81. data/ext/capn_proto/struct_schema.cc +59 -0
  82. data/ext/capn_proto/struct_schema.h +23 -0
  83. data/ext/capn_proto/util.cc +30 -0
  84. data/ext/capn_proto/util.h +17 -0
  85. data/lib/capn_proto.rb +231 -0
  86. data/lib/capn_proto/version.rb +3 -0
  87. data/media/captain_proto.png +0 -0
  88. data/media/captain_proto_small.png +0 -0
  89. data/spec/addressbook.bin +0 -0
  90. data/spec/addressbook.capnp +31 -0
  91. data/spec/capn_proto_spec.rb +80 -0
  92. data/spec/create_test_data.py +38 -0
  93. data/spec/spec_helper.rb +8 -0
  94. data/tests/hidraCordatus.capnp +16 -0
  95. data/tests/hidraCordatusEmployer.rb +33 -0
  96. data/tests/hidraCordatusMaster.rb +51 -0
  97. metadata +216 -0
@@ -0,0 +1,80 @@
1
+ #include "ruby_capn_proto.h"
2
+ #include "class_builder.h"
3
+
4
+ namespace ruby_capn_proto {
5
+
6
+ VALUE defineClass(const char *name, VALUE superclass = rb_cObject) {
7
+ VALUE CapnProto = rb_define_module("CapnProto");
8
+ VALUE klass = rb_define_class_under(CapnProto, name, superclass);
9
+ // rb_funcall(klass, rb_intern("private_class_method"), 1, rb_str_new2("new"));
10
+ return klass;
11
+ }
12
+
13
+ ClassBuilder::ClassBuilder(const char* name, VALUE superclass) {
14
+ this->value = defineClass(name, superclass);
15
+ }
16
+ ClassBuilder::ClassBuilder(const char* name, const char* supername) {
17
+ VALUE superclass = defineClass(supername);
18
+ this->value = defineClass(name, superclass);
19
+ }
20
+
21
+ ClassBuilder& ClassBuilder::defineAlloc(VALUE (*impl)(VALUE)) {
22
+ rb_define_alloc_func(this->value, (VALUE (*)(VALUE))impl);
23
+ return *this;
24
+ }
25
+
26
+ ClassBuilder& ClassBuilder::defineConst(const char* name, VALUE value) {
27
+ rb_define_const(this->value, name, value);
28
+ return *this;
29
+ }
30
+
31
+ ClassBuilder& ClassBuilder::defineMethod(const char* name, VALUE (*impl)(int, VALUE*, VALUE)) {
32
+ rb_define_method(this->value, name, (VALUE (*)(...))impl, -1);
33
+ return *this;
34
+ }
35
+ ClassBuilder& ClassBuilder::defineMethod(const char* name, VALUE (*impl)(VALUE)) {
36
+ rb_define_method(this->value, name, (VALUE (*)(...))impl, 0);
37
+ return *this;
38
+ }
39
+ ClassBuilder& ClassBuilder::defineMethod(const char* name, VALUE (*impl)(VALUE, VALUE)) {
40
+ rb_define_method(this->value, name, (VALUE (*)(...))impl, 1);
41
+ return *this;
42
+ }
43
+ ClassBuilder& ClassBuilder::defineMethod(const char* name, VALUE (*impl)(VALUE, VALUE, VALUE)) {
44
+ rb_define_method(this->value, name, (VALUE (*)(...))impl, 2);
45
+ return *this;
46
+ }
47
+ ClassBuilder& ClassBuilder::defineMethod(const char* name, VALUE (*impl)(VALUE, VALUE, VALUE, VALUE)) {
48
+ rb_define_method(this->value, name, (VALUE (*)(...))impl, 3);
49
+ return *this;
50
+ }
51
+ ClassBuilder& ClassBuilder::defineSingletonMethod(const char* name, VALUE (*impl)(int, VALUE*, VALUE)) {
52
+ rb_define_singleton_method(this->value, name, (VALUE (*)(...))impl, -1);
53
+ return *this;
54
+ }
55
+ ClassBuilder& ClassBuilder::defineSingletonMethod(const char* name, VALUE (*impl)(VALUE)) {
56
+ rb_define_singleton_method(this->value, name, (VALUE (*)(...))impl, 0);
57
+ return *this;
58
+ }
59
+ ClassBuilder& ClassBuilder::defineSingletonMethod(const char* name, VALUE (*impl)(VALUE, VALUE)) {
60
+ rb_define_singleton_method(this->value, name, (VALUE (*)(...))impl, 1);
61
+ return *this;
62
+ }
63
+ ClassBuilder& ClassBuilder::defineSingletonMethod(const char* name, VALUE (*impl)(VALUE, VALUE, VALUE)) {
64
+ rb_define_singleton_method(this->value, name, (VALUE (*)(...))impl, 2);
65
+ return *this;
66
+ }
67
+ ClassBuilder& ClassBuilder::defineSingletonMethod(const char* name, VALUE (*impl)(VALUE, VALUE, VALUE, VALUE)) {
68
+ rb_define_singleton_method(this->value, name, (VALUE (*)(...))impl, 3);
69
+ return *this;
70
+ }
71
+ ClassBuilder& ClassBuilder::defineEnumConst(const char* name, int value) {
72
+ rb_define_const(this->value, name, INT2FIX(value));
73
+ return *this;
74
+ }
75
+ ClassBuilder& ClassBuilder::store(VALUE* storage) {
76
+ rb_gc_register_address(storage);
77
+ *storage = this->value;
78
+ return *this;
79
+ }
80
+ }
@@ -0,0 +1,72 @@
1
+ #ifndef CLASS_BUILDER_H
2
+ #define CLASS_BUILDER_H
3
+
4
+ #include "ruby_capn_proto.h"
5
+
6
+ namespace ruby_capn_proto {
7
+ class ClassBuilder {
8
+ public:
9
+ ClassBuilder() {};
10
+ ClassBuilder(const char* name, VALUE superclass = rb_cObject);
11
+ ClassBuilder(const char* name, const char* supername);
12
+ ClassBuilder& defineAlloc(VALUE (*impl)(VALUE));
13
+ ClassBuilder& defineConst(const char* name, VALUE value);
14
+ ClassBuilder& defineMethod(const char* name, VALUE (*impl)(int, VALUE*, VALUE));
15
+ ClassBuilder& defineMethod(const char* name, VALUE (*impl)(VALUE));
16
+ ClassBuilder& defineMethod(const char* name, VALUE (*impl)(VALUE, VALUE));
17
+ ClassBuilder& defineMethod(const char* name, VALUE (*impl)(VALUE, VALUE, VALUE));
18
+ ClassBuilder& defineMethod(const char* name, VALUE (*impl)(VALUE, VALUE, VALUE, VALUE));
19
+ ClassBuilder& defineSingletonMethod(const char* name, VALUE (*impl)(int, VALUE*, VALUE));
20
+ ClassBuilder& defineSingletonMethod(const char* name, VALUE (*impl)(VALUE));
21
+ ClassBuilder& defineSingletonMethod(const char* name, VALUE (*impl)(VALUE, VALUE));
22
+ ClassBuilder& defineSingletonMethod(const char* name, VALUE (*impl)(VALUE, VALUE, VALUE));
23
+ ClassBuilder& defineSingletonMethod(const char* name, VALUE (*impl)(VALUE, VALUE, VALUE, VALUE));
24
+ ClassBuilder& defineEnumConst(const char* name, int value);
25
+ ClassBuilder& store(VALUE* storage);
26
+ inline operator VALUE() {return this->value;}
27
+ protected:
28
+ VALUE value;
29
+ };
30
+
31
+ template <VALUE(* f)(int, VALUE*, VALUE)>
32
+ VALUE handleExceptions(int argc, VALUE* argv, VALUE self)
33
+ {
34
+ try {
35
+ return f(argc, argv, self);
36
+ } catch (...) {
37
+ rb_raise(rb_eRuntimeError, "caught unkown error");
38
+ }
39
+ }
40
+
41
+ template <VALUE(* f)(VALUE)>
42
+ VALUE handleExceptions(VALUE self)
43
+ {
44
+ return f(self);
45
+ }
46
+
47
+ template <VALUE(* f)(VALUE, VALUE)>
48
+ VALUE handleExceptions(VALUE self, VALUE arg1)
49
+ {
50
+ return f(self, arg1);
51
+ }
52
+
53
+ template <VALUE(* f)(VALUE, VALUE, VALUE)>
54
+ VALUE handleExceptions(VALUE self, VALUE arg1, VALUE arg2)
55
+ {
56
+ return f(self, arg1, arg2);
57
+ }
58
+
59
+ template <VALUE(* f)(VALUE, VALUE, VALUE, VALUE)>
60
+ VALUE handleExceptions(VALUE self, VALUE arg2, VALUE arg1, VALUE arg3)
61
+ {
62
+ return f(self, arg1, arg2, arg3);
63
+ }
64
+
65
+ template <VALUE(* f)(VALUE, VALUE, VALUE, VALUE, VALUE)>
66
+ VALUE handleExceptions(VALUE self, VALUE arg2, VALUE arg1, VALUE arg3, VALUE arg4)
67
+ {
68
+ return f(self, arg1, arg2, arg3, arg4);
69
+ }
70
+ }
71
+
72
+ #endif /* CLASS_BUILDER_H */
@@ -0,0 +1,126 @@
1
+ require 'shellwords'
2
+ require 'tmpdir'
3
+
4
+ # Discovers support for C++11 features,
5
+ # and any required CXXFLAGS for such features.
6
+ class CXXCompiler
7
+ CXX_COMPILER_FEATURES = <<-CODE
8
+ template <typename T>
9
+ struct check
10
+ {
11
+ static_assert(sizeof(int) <= sizeof(T), "not big enough");
12
+ };
13
+
14
+ typedef check<check<bool>> right_angle_brackets;
15
+
16
+ int a;
17
+ decltype(a) b;
18
+
19
+ typedef check<int> check_type;
20
+ check_type c;
21
+ check_type&& cr = static_cast<check_type&&>(c);
22
+
23
+ #ifdef __has_include
24
+ #if __has_include(<type_traits>)
25
+ #include <type_traits>
26
+ #endif
27
+ #endif
28
+ CODE
29
+
30
+ CXX_LIBRARY_FEATURES = <<-CODE
31
+ #include <initializer_list>
32
+ #include <unordered_map>
33
+ #include <atomic>
34
+ #include <thread>
35
+ CODE
36
+
37
+ # env: The environment variables (e.g. CXX, CXXFLAGS).
38
+ def initialize(env)
39
+ @env = env.dup
40
+ @exist = system("command -v #{@env['CXX'].shellescape} >/dev/null 2>&1")
41
+ end
42
+
43
+ # True if the compiler is accessible on the $PATH.
44
+ def exist?
45
+ @exist
46
+ end
47
+
48
+ # True if support for C++11 was detected, false otherwise.
49
+ def has_cxx11_compiler_support?
50
+ !!std_flag
51
+ end
52
+
53
+ # True if support for C++11 libraries was detected, false otherwise.
54
+ def has_cxx11_library_support?
55
+ !!stdlib_flag
56
+ end
57
+
58
+ # The required std flag (e.g. '-std=c++11'),
59
+ # empty string if unecessary given the current environment and/or compiler,
60
+ # or nil in the case where the compiler has no support.
61
+ def std_flag
62
+ test_compiler_flags(@env)
63
+ @std_flag
64
+ end
65
+
66
+ # The required stdlib flag (e.g. '-stdlib=libc++'),
67
+ # empty string if unecessary given the current environment and/or compiler,
68
+ # or nil in the case where the compiler has no support.
69
+ def stdlib_flag
70
+ test_compiler_flags(@env)
71
+ @stdlib_flag
72
+ end
73
+
74
+ private
75
+
76
+ # Detect any required flags.
77
+ def test_compiler_flags(env)
78
+ return if @tested || !exist?
79
+ @tested = true
80
+
81
+ cxxflags = (env['CXXFLAGS'] || '')
82
+ env = env.dup
83
+
84
+ flags = ['', '-std=gnu++11', '-std=gnu++0x', '-std=c++11', '-std=c++0x']
85
+ @std_flag = flags.detect do |flag|
86
+ env['CXXFLAGS'] = [cxxflags, flag].join(' ')
87
+ compile(CXX_COMPILER_FEATURES, env)
88
+ end
89
+
90
+ return unless @std_flag
91
+
92
+ env = env.dup
93
+ flags = ['', '-stdlib=libc++']
94
+ @stdlib_flag = flags.detect do |flag|
95
+ env['CXXFLAGS'] = [cxxflags, std_flag, flag].join(' ')
96
+ compile(CXX_LIBRARY_FEATURES, env)
97
+ end
98
+ end
99
+
100
+ # Compile a snippet of C++, returning true or false to indicate
101
+ # success.
102
+ def compile(code, env)
103
+ Dir.mktmpdir do |dir|
104
+ Dir.chdir(dir) do
105
+ File.open("test.cc", "w") {|f| f.write(code)}
106
+ system("#{env['CXX'].shellescape} #{env['CXXFLAGS']} -c test.cc >/dev/null 2>&1")
107
+ end
108
+ end
109
+ end
110
+ end
111
+
112
+ if $0 == __FILE__
113
+ compiler = CXXCompiler.new(ENV.to_hash)
114
+ cxx = ENV['CXX']
115
+ cxxflags = ENV['CXXFLAGS']
116
+ extra_cxxflags = [compiler.std_flag, compiler.stdlib_flag].join(' ')
117
+ compiler_support = compiler.has_cxx11_compiler_support? ? 'YES' : 'NO'
118
+ lib_support = compiler.has_cxx11_library_support? ? 'YES' : 'NO'
119
+
120
+ puts " given CXX = #{cxx}"
121
+ puts " given CXXFLAGS = #{cxxflags}"
122
+ puts "additional CXXFLAGS = #{extra_cxxflags}"
123
+ puts ""
124
+ puts "Has C++11 compiler support? #{compiler_support}"
125
+ puts "Has C++11 library support? #{lib_support}"
126
+ end
@@ -0,0 +1,73 @@
1
+ #include "ruby_capn_proto.h"
2
+ #include "capability_client.h"
3
+ #include "dynamic_capability_client.h"
4
+ #include "interface_schema.h"
5
+ #include "interface_method.h"
6
+ #include "remote_promise.h"
7
+ #include "exception.h"
8
+ #include "class_builder.h"
9
+ #include "util.h"
10
+
11
+ namespace ruby_capn_proto {
12
+ using WrappedType = capnp::DynamicCapability::Client;
13
+ VALUE DynamicCapabilityClient::Class;
14
+
15
+ void DynamicCapabilityClient::Init() {
16
+ ClassBuilder("DynamicCapabilityClient", rb_cObject).
17
+ defineAlloc(&alloc).
18
+ defineMethod("request_and_send" , &request_and_send).
19
+ store(&Class);
20
+ }
21
+
22
+ void DynamicCapabilityClient::free(WrappedType* p) {
23
+ p->~Client();
24
+ ruby_xfree(p);
25
+ }
26
+
27
+ VALUE DynamicCapabilityClient::alloc(VALUE klass) {
28
+ return Data_Wrap_Struct(klass, NULL, free, ruby_xmalloc(sizeof(WrappedType)));
29
+ }
30
+
31
+ WrappedType* DynamicCapabilityClient::unwrap(VALUE self) {
32
+ WrappedType* p;
33
+ Data_Get_Struct(self, WrappedType, p);
34
+ return p;
35
+ }
36
+
37
+ VALUE DynamicCapabilityClient::create(VALUE client, VALUE interschema) {
38
+
39
+ VALUE self = alloc(Class);
40
+ WrappedType* rb_self = unwrap(self);
41
+ auto dyncap = CapabilityClient::unwrap(client)->castAs<capnp::DynamicCapability>(*InterfaceSchema::unwrap(interschema));
42
+ new (rb_self) capnp::DynamicCapability::Client(dyncap);
43
+
44
+ return self;
45
+ }
46
+
47
+ VALUE DynamicCapabilityClient::create(WrappedType native_client){
48
+ VALUE self = alloc(Class);
49
+ WrappedType* rb_self = unwrap(self);
50
+ new (rb_self) capnp::DynamicCapability::Client(native_client);
51
+
52
+ return self;
53
+ }
54
+
55
+ VALUE DynamicCapabilityClient::request_and_send(VALUE self , VALUE rb_method , VALUE arrays){
56
+ // have, a method and a list of lists each list containing a value to set
57
+ // return, a remote promise.
58
+ // Data must be a array of arrays
59
+ // arrays must be like ['expression','literal','3']
60
+ // this will set in the expression param literal = 3
61
+ try{
62
+ auto* method = InterfaceMethod::unwrap(rb_method);
63
+ auto request = unwrap(self)->newRequest(*method);
64
+
65
+ RemotePromise::setParam(&request,arrays);
66
+
67
+ capnp::RemotePromise<capnp::DynamicStruct> r = request.send();
68
+ return RemotePromise::create(r);
69
+ }catch(kj::Exception e){
70
+ Exception::raise(e);
71
+ }
72
+ }
73
+ }
@@ -0,0 +1,22 @@
1
+ #ifndef DYNAMIC_CAPABILITY_CLIENT_H
2
+ #define DYNAMIC_CAPABILITY_CLIENT_H
3
+
4
+ #include "ruby_capn_proto.h"
5
+
6
+ namespace ruby_capn_proto {
7
+ class DynamicCapabilityClient {
8
+ public:
9
+ using WrappedType = capnp::DynamicCapability::Client;
10
+ static void Init();
11
+ static VALUE alloc(VALUE klass);
12
+ static VALUE create(VALUE capclient, VALUE schema);
13
+ static VALUE create(WrappedType native_dynclient);
14
+ static void free(WrappedType* p);
15
+ static WrappedType* unwrap(VALUE self);
16
+ static VALUE request_and_send(VALUE self, VALUE method, VALUE data);
17
+ static VALUE Class;
18
+ };
19
+ }
20
+
21
+
22
+ #endif /* DYNAMIC_CAPABILITY_CLIENT_H */
@@ -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
+ }