capn_proto 0.0.1.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/.gitignore +5 -0
  2. data/Gemfile +2 -0
  3. data/LICENSE +19 -0
  4. data/README.md +42 -0
  5. data/Rakefile +25 -0
  6. data/capn_proto.gemspec +33 -0
  7. data/examples/addressbook.bin +0 -0
  8. data/examples/addressbook.capnp +31 -0
  9. data/examples/create_test_data.py +39 -0
  10. data/examples/example.rb +38 -0
  11. data/ext/capn_proto/.ycm_extra_conf.py +65 -0
  12. data/ext/capn_proto/.ycm_extra_conf.pyc +0 -0
  13. data/ext/capn_proto/class_builder.cc +80 -0
  14. data/ext/capn_proto/class_builder.h +72 -0
  15. data/ext/capn_proto/dynamic_list_reader.cc +52 -0
  16. data/ext/capn_proto/dynamic_list_reader.h +23 -0
  17. data/ext/capn_proto/dynamic_struct_reader.cc +59 -0
  18. data/ext/capn_proto/dynamic_struct_reader.h +23 -0
  19. data/ext/capn_proto/dynamic_value_reader.cc +50 -0
  20. data/ext/capn_proto/dynamic_value_reader.h +13 -0
  21. data/ext/capn_proto/exception.cc +24 -0
  22. data/ext/capn_proto/exception.h +18 -0
  23. data/ext/capn_proto/extconf.rb +29 -0
  24. data/ext/capn_proto/field_list.cc +51 -0
  25. data/ext/capn_proto/field_list.h +23 -0
  26. data/ext/capn_proto/init.cc +34 -0
  27. data/ext/capn_proto/list_nested_node_reader.cc +50 -0
  28. data/ext/capn_proto/list_nested_node_reader.h +24 -0
  29. data/ext/capn_proto/message_reader.cc +30 -0
  30. data/ext/capn_proto/message_reader.h +17 -0
  31. data/ext/capn_proto/nested_node_reader.cc +42 -0
  32. data/ext/capn_proto/nested_node_reader.h +21 -0
  33. data/ext/capn_proto/parsed_schema.cc +58 -0
  34. data/ext/capn_proto/parsed_schema.h +23 -0
  35. data/ext/capn_proto/rb.cc +0 -0
  36. data/ext/capn_proto/rb.h +0 -0
  37. data/ext/capn_proto/ruby_capn_proto.cc +4 -0
  38. data/ext/capn_proto/ruby_capn_proto.h +38 -0
  39. data/ext/capn_proto/schema_node_reader.cc +51 -0
  40. data/ext/capn_proto/schema_node_reader.h +22 -0
  41. data/ext/capn_proto/schema_parser.cc +53 -0
  42. data/ext/capn_proto/schema_parser.h +20 -0
  43. data/ext/capn_proto/stream_fd_message_reader.cc +53 -0
  44. data/ext/capn_proto/stream_fd_message_reader.h +21 -0
  45. data/ext/capn_proto/struct_schema.cc +57 -0
  46. data/ext/capn_proto/struct_schema.h +23 -0
  47. data/ext/capn_proto/util.cc +25 -0
  48. data/ext/capn_proto/util.h +16 -0
  49. data/lib/capn_proto/version.rb +3 -0
  50. data/lib/capn_proto.rb +88 -0
  51. data/media/captain_proto.png +0 -0
  52. data/media/captain_proto_small.png +0 -0
  53. data/spec/addressbook.bin +0 -0
  54. data/spec/addressbook.capnp +31 -0
  55. data/spec/capn_proto_spec.rb +7 -0
  56. data/spec/create_test_data.py +38 -0
  57. metadata +188 -0
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ Gemfile.lock
2
+ *.bundle
3
+ tmp
4
+ .env
5
+ pkg
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2013 Charles Strahan
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,42 @@
1
+ [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/cstrahan/capnp-ruby/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
2
+
3
+ ![Cap'n Proto][logo]
4
+
5
+ # Ruby Edition
6
+
7
+ This here is a [Ruby][ruby] wrapper for the official C++ implementation of [Cap'n Proto][capnp].
8
+
9
+ # Installing
10
+
11
+ First [install libcapnp][libcapnp-install], then install the gem:
12
+
13
+ ```bash
14
+ gem install capn_proto
15
+ ```
16
+
17
+ Remember to set the `CXX` and `CXXFLAGS` environment variables as necessary. As an OSX user, having followed the [instructions for installing libcapnp on OSX][libcapnp-install], the correct incantation is as follows:
18
+
19
+ ```bash
20
+ export CXX=$HOME/clang-3.2/bin/clang++
21
+ export CXXFLAGS="-std=c++11 -stdlib=libc++"
22
+ gem install capn_proto
23
+ ```
24
+
25
+ # License
26
+
27
+ The MIT License
28
+
29
+ # Status
30
+
31
+ - [x] Schema parsing (and recursive Module definition)
32
+ - [x] Message reading
33
+ - [ ] Message writing
34
+
35
+ Proper support for [JRuby][jruby] will come after I implement support for Java.
36
+
37
+ [logo]: https://raw.github.com/cstrahan/capnp-ruby/master/media/captain_proto_small.png "Cap'n Proto"
38
+ [ruby]: http://www.ruby-lang.org/ "Ruby"
39
+ [capnp]: http://kentonv.github.io/capnproto/ "Cap'n Proto"
40
+ [jruby]: http://jruby.org/ "JRuby"
41
+ [libcapnp-install]: http://kentonv.github.io/capnproto/install.html "Installing Cap'n Proto"
42
+ [mit-license]: http://opensource.org/licenses/MIT "MIT License"
data/Rakefile ADDED
@@ -0,0 +1,25 @@
1
+ GEMSPEC = eval(File.read('capn_proto.gemspec'))
2
+
3
+ require 'rubygems/package_task'
4
+ Gem::PackageTask.new(GEMSPEC) do |pkg|
5
+ end
6
+
7
+ require 'rake/extensiontask'
8
+ Rake::ExtensionTask.new('init', GEMSPEC) do |ext|
9
+ ext.ext_dir = 'ext/capn_proto'
10
+ ext.lib_dir = 'lib/capn_proto'
11
+ ext.source_pattern = "*.{cc,h}"
12
+ end
13
+
14
+ require 'rspec/core/rake_task'
15
+ RSpec::Core::RakeTask.new(:spec) do |config|
16
+ end
17
+
18
+ task :default => [:compile, :spec]
19
+
20
+ task :console do
21
+ $: << File.expand_path("../lib", __FILE__)
22
+ require 'irb'
23
+ ARGV.clear
24
+ IRB.start
25
+ end
@@ -0,0 +1,33 @@
1
+ require File.expand_path('../lib/capn_proto/version', __FILE__)
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'capn_proto'
5
+ s.version = CapnProto::VERSION
6
+
7
+ s.summary = "Cap'n Proto (libcapnp) bindings for Ruby."
8
+
9
+ s.description =
10
+ "This gem wraps the official C++ implementation of Cap'n Proto " \
11
+ "(libcapnp). " \
12
+ "From the Cap'n Proto documentation: " \
13
+ "\"Cap'n Proto is an insanely fast data interchange format and " \
14
+ "capability-based RPC system. Think JSON, except binary. " \
15
+ "Or think Protocol Buffers, except faster.\""
16
+
17
+ s.homepage = 'https://github.com/cstrahan/capnp-ruby'
18
+
19
+ s.authors = ['Charles Strahan']
20
+ s.email = ['charles.c.strahan@gmail.com']
21
+
22
+ s.add_development_dependency 'rspec', '2.14.1'
23
+ s.add_development_dependency 'rake'
24
+ s.add_development_dependency 'rake-compiler', '0.7.6'
25
+
26
+ s.add_development_dependency 'awesome_print'
27
+ s.add_development_dependency 'interactive_editor'
28
+
29
+ s.extensions = ['ext/capn_proto/extconf.rb']
30
+ s.require_paths = ['lib']
31
+
32
+ s.files = `git ls-files`.split("\n")
33
+ end
Binary file
@@ -0,0 +1,31 @@
1
+ @0x9eb32e19f86ee174;
2
+
3
+ struct Person {
4
+ id @0 :UInt32;
5
+ name @1 :Text;
6
+ email @2 :Text;
7
+ phones @3 :List(PhoneNumber);
8
+
9
+ struct PhoneNumber {
10
+ number @0 :Text;
11
+ type @1 :Type;
12
+
13
+ enum Type {
14
+ mobile @0;
15
+ home @1;
16
+ work @2;
17
+ }
18
+ }
19
+
20
+ employment :union {
21
+ unemployed @4 :Void;
22
+ employer @5 :Text;
23
+ school @6 :Text;
24
+ selfEmployed @7 :Void;
25
+ # We assume that a person is only one of these.
26
+ }
27
+ }
28
+
29
+ struct AddressBook {
30
+ people @0 :List(Person);
31
+ }
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env python
2
+ from __future__ import print_function
3
+ import os
4
+ import capnp
5
+
6
+ this_dir = os.path.dirname(__file__)
7
+ out_path = os.path.join(this_dir, 'addressbook.bin')
8
+ addressbook = capnp.load(os.path.join(this_dir, 'addressbook.capnp'))
9
+
10
+ def writeAddressBook(file):
11
+ addresses = addressbook.AddressBook.newMessage()
12
+ people = addresses.init('people', 2)
13
+
14
+ alice = people[0]
15
+ alice.id = 123
16
+ alice.name = 'Alice'
17
+ alice.email = 'alice@example.com'
18
+ alicePhones = alice.init('phones', 1)
19
+ alicePhones[0].number = "555-1212"
20
+ alicePhones[0].type = 'mobile'
21
+ alice.employment.school = "MIT"
22
+
23
+ bob = people[1]
24
+ bob.id = 456
25
+ bob.name = 'Bob'
26
+ bob.email = 'bob@example.com'
27
+ bobPhones = bob.init('phones', 2)
28
+ bobPhones[0].number = "555-4567"
29
+ bobPhones[0].type = 'home'
30
+ bobPhones[1].number = "555-7654"
31
+ bobPhones[1].type = 'work'
32
+ bob.employment.unemployed = None
33
+
34
+ addresses.writeTo(file)
35
+
36
+
37
+ if __name__ == '__main__':
38
+ f = open(out_path, 'w')
39
+ writeAddressBook(f)
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env ruby
2
+ $: << File.expand_path("../../lib", __FILE__)
3
+ $: << File.expand_path("../../ext", __FILE__)
4
+ require 'capn_proto'
5
+
6
+ ADDRESSBOOK_SCHEMA = File.expand_path("../addressbook.capnp", __FILE__);
7
+ MESSAGE = File.expand_path("../addressbook.bin", __FILE__);
8
+
9
+ module AddressBook extend CapnProto::SchemaLoader
10
+ load_schema(ADDRESSBOOK_SCHEMA)
11
+ end
12
+
13
+ def print_address_book(file)
14
+ addresses = AddressBook::AddressBook.read_from(file)
15
+
16
+ addresses.people.each do |person|
17
+ puts "#{person.name} : #{person.email}"
18
+ person.phones.each do |phone|
19
+ puts "#{phone.type} : #{phone.number}"
20
+ end
21
+
22
+ which = person.employment.which
23
+ puts which
24
+
25
+ if which == "unemployed"
26
+ puts "unemployed"
27
+ elsif which == 'employer'
28
+ puts "employer: #{person.employment.employer}"
29
+ elsif which == "school"
30
+ puts "student at: #{person.employment.school}"
31
+ elsif which == "selfEmployed"
32
+ puts "self employed"
33
+ end
34
+ end
35
+ end
36
+
37
+ file = File.open(MESSAGE, "rb")
38
+ print_address_book(file)
@@ -0,0 +1,65 @@
1
+ # vim: ts=2 et sw=2 sts=2
2
+
3
+ import os
4
+ import ycm_core
5
+ import glob
6
+ import subprocess
7
+
8
+ def RubyInclude():
9
+ cmd = ["ruby", "-e", "print RbConfig::CONFIG['rubyhdrdir']"]
10
+ process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
11
+ rubyhdrdir = process.stdout.read()
12
+ return rubyhdrdir
13
+
14
+ flags = [
15
+ '-Wall',
16
+ '-Wextra',
17
+ '-Werror',
18
+ '-fexceptions',
19
+ '-Wc++98-compat',
20
+ '-std=c++11',
21
+ '-x', 'c++',
22
+ '-I', '.',
23
+ '-I', '/usr/local/include',
24
+ '-I', RubyInclude(),
25
+ ]
26
+
27
+ def DirectoryOfThisScript():
28
+ return os.path.dirname( os.path.abspath( __file__ ) )
29
+
30
+ def MakeRelativePathsInFlagsAbsolute( flags, working_directory ):
31
+ if not working_directory:
32
+ return list( flags )
33
+ new_flags = []
34
+ make_next_absolute = False
35
+ path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ]
36
+ for flag in flags:
37
+ new_flag = flag
38
+
39
+ if make_next_absolute:
40
+ make_next_absolute = False
41
+ if not flag.startswith( '/' ):
42
+ new_flag = os.path.join( working_directory, flag )
43
+
44
+ for path_flag in path_flags:
45
+ if flag == path_flag:
46
+ make_next_absolute = True
47
+ break
48
+
49
+ if flag.startswith( path_flag ):
50
+ path = flag[ len( path_flag ): ]
51
+ new_flag = path_flag + os.path.join( working_directory, path )
52
+ break
53
+
54
+ if new_flag:
55
+ new_flags.append( new_flag )
56
+ return new_flags
57
+
58
+ def FlagsForFile( filename ):
59
+ relative_to = DirectoryOfThisScript()
60
+ final_flags = MakeRelativePathsInFlagsAbsolute( flags, relative_to )
61
+
62
+ return {
63
+ 'flags': final_flags,
64
+ 'do_cache': True
65
+ }
Binary file
@@ -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,52 @@
1
+ #include "ruby_capn_proto.h"
2
+ #include "dynamic_list_reader.h"
3
+ #include "dynamic_value_reader.h"
4
+ #include "class_builder.h"
5
+
6
+ namespace ruby_capn_proto {
7
+ using WrappedType = capnp::DynamicList::Reader;
8
+ VALUE DynamicListReader::Class;
9
+
10
+ void DynamicListReader::Init() {
11
+ ClassBuilder("DynamicListReader", rb_cObject).
12
+ defineAlloc(&alloc).
13
+ defineMethod("[]", &get).
14
+ defineMethod("size", &size).
15
+ store(&Class);
16
+ }
17
+
18
+ VALUE DynamicListReader::alloc(VALUE klass) {
19
+ return Data_Wrap_Struct(klass, NULL, free, ruby_xmalloc(sizeof(WrappedType)));
20
+ }
21
+
22
+ void DynamicListReader::free(WrappedType* p) {
23
+ p->~Reader();
24
+ ruby_xfree(p);
25
+ }
26
+
27
+ WrappedType* DynamicListReader::unwrap(VALUE self) {
28
+ WrappedType* p;
29
+ Data_Get_Struct(self, WrappedType, p);
30
+ return p;
31
+ }
32
+
33
+ VALUE DynamicListReader::create(WrappedType reader, VALUE parent) {
34
+ auto rb_obj = alloc(Class);
35
+ WrappedType* wrapped = unwrap(rb_obj);
36
+ *wrapped = kj::mv(reader);
37
+
38
+ return rb_obj;
39
+ }
40
+
41
+ VALUE DynamicListReader::size(VALUE self) {
42
+ return INT2FIX(unwrap(self)->size());
43
+ }
44
+
45
+ VALUE DynamicListReader::get(VALUE self, VALUE rb_index) {
46
+ auto reader = *unwrap(self);
47
+ auto index = FIX2INT(rb_index);
48
+ auto size = reader.size();
49
+
50
+ return DynamicValueReader::to_ruby(reader[index], self);
51
+ }
52
+ }
@@ -0,0 +1,23 @@
1
+ #ifndef DYNAMIC_LIST_READER_H
2
+ #define DYNAMIC_LIST_READER_H
3
+
4
+ #include "ruby_capn_proto.h"
5
+
6
+ namespace ruby_capn_proto {
7
+ class DynamicListReader {
8
+ public:
9
+ using WrappedType = capnp::DynamicList::Reader;
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 size(VALUE self);
18
+
19
+ static VALUE Class;
20
+ };
21
+ }
22
+
23
+ #endif /* DYNAMIC_LIST_READER_H */
@@ -0,0 +1,59 @@
1
+ #include "ruby_capn_proto.h"
2
+ #include "dynamic_struct_reader.h"
3
+ #include "dynamic_value_reader.h"
4
+ #include "class_builder.h"
5
+ #include "util.h"
6
+
7
+ namespace ruby_capn_proto {
8
+ using WrappedType = capnp::DynamicStruct::Reader;
9
+ VALUE DynamicStructReader::Class;
10
+
11
+ void DynamicStructReader::Init() {
12
+ ClassBuilder("DynamicStructReader", rb_cObject).
13
+ defineAlloc(&alloc).
14
+ defineMethod("which", &which).
15
+ defineMethod("[]", &get).
16
+ store(&Class);
17
+ }
18
+
19
+ void DynamicStructReader::free(WrappedType* p) {
20
+ p->~Reader();
21
+ ruby_xfree(p);
22
+ }
23
+
24
+ VALUE DynamicStructReader::alloc(VALUE klass) {
25
+ return Data_Wrap_Struct(klass, NULL, free, ruby_xmalloc(sizeof(WrappedType)));
26
+ }
27
+
28
+ WrappedType* DynamicStructReader::unwrap(VALUE self) {
29
+ WrappedType* p;
30
+ Data_Get_Struct(self, WrappedType, p);
31
+ return p;
32
+ }
33
+
34
+ VALUE DynamicStructReader::create(WrappedType reader) {
35
+ VALUE rb_obj = alloc(Class);
36
+ WrappedType* wrapped = unwrap(rb_obj);
37
+ *wrapped = kj::mv(reader);
38
+
39
+ return rb_obj;
40
+ }
41
+
42
+ VALUE DynamicStructReader::get(VALUE self, VALUE rb_name) {
43
+ auto reader = *unwrap(self);
44
+ auto name = Util::toString(rb_name);
45
+
46
+ return DynamicValueReader::to_ruby(reader.get(name), self);
47
+ }
48
+
49
+ VALUE DynamicStructReader::which(VALUE self) {
50
+ auto schema_maybe = unwrap(self)->which();
51
+ KJ_IF_MAYBE(schema, schema_maybe) {
52
+ auto name = schema->getProto().getName();
53
+ return rb_str_new(name.begin(), name.size());
54
+ } else {
55
+ // throw std::invalid_argument("member was null");
56
+ return Qnil;
57
+ }
58
+ }
59
+ }
@@ -0,0 +1,23 @@
1
+ #ifndef DYNAMIC_STRUCT_READER_H
2
+ #define DYNAMIC_STRUCT_READER_H
3
+
4
+ #include "ruby_capn_proto.h"
5
+
6
+ namespace ruby_capn_proto {
7
+ class DynamicStructReader {
8
+ public:
9
+ using WrappedType = capnp::DynamicStruct::Reader;
10
+ static void Init();
11
+ static VALUE alloc(VALUE klass);
12
+ static VALUE create(WrappedType reader);
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 name);
17
+
18
+ static VALUE Class;
19
+ };
20
+ }
21
+
22
+
23
+ #endif /* DYNAMIC_STRUCT_READER_H */
@@ -0,0 +1,50 @@
1
+ #include "ruby_capn_proto.h"
2
+ #include "dynamic_value_reader.h"
3
+ #include "dynamic_list_reader.h"
4
+ #include "dynamic_struct_reader.h"
5
+
6
+ namespace ruby_capn_proto {
7
+ VALUE DynamicValueReader::to_ruby(capnp::DynamicValue::Reader value, VALUE parent) {
8
+ switch (value.getType())
9
+ {
10
+ case capnp::DynamicValue::BOOL:
11
+ return value.as<bool>() ? Qtrue : Qfalse;
12
+ case capnp::DynamicValue::INT:
13
+ return INT2FIX(value.as<int64_t>());
14
+ case capnp::DynamicValue::UINT:
15
+ return INT2FIX(value.as<uint64_t>());
16
+ case capnp::DynamicValue::FLOAT:
17
+ return rb_float_new(value.as<double>());
18
+ case capnp::DynamicValue::TEXT:
19
+ {
20
+ auto text = value.as<capnp::Text>();
21
+ return rb_str_new(text.begin(), text.size());
22
+ }
23
+ case capnp::DynamicValue::DATA:
24
+ {
25
+ auto data = value.as<capnp::Data>();
26
+ return rb_str_new((const char*)data.begin(), data.size());
27
+ }
28
+ case capnp::DynamicValue::LIST:
29
+ return DynamicListReader::create(value.as<capnp::DynamicList>(), parent);
30
+ // return Qnil;
31
+ case capnp::DynamicValue::STRUCT:
32
+ return DynamicStructReader::create(value.as<capnp::DynamicStruct>());
33
+ case capnp::DynamicValue::ENUM:
34
+ {
35
+ auto enumerant_maybe = value.as<capnp::DynamicEnum>().getEnumerant();
36
+ KJ_IF_MAYBE(enumerant, enumerant_maybe) {
37
+ auto name = enumerant->getProto().getName();
38
+ return rb_str_new(name.begin(), name.size());
39
+ } else {
40
+ return Qnil;
41
+ }
42
+ }
43
+ case capnp::DynamicValue::VOID:
44
+ return Qnil;
45
+ case capnp::DynamicValue::UNKNOWN:
46
+ default:
47
+ return Qnil;
48
+ }
49
+ }
50
+ }