capn_proto 0.0.1.alpha.1

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 (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
+ }