capn_proto 0.0.1.alpha.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/Gemfile +2 -0
- data/LICENSE +19 -0
- data/README.md +42 -0
- data/Rakefile +25 -0
- data/capn_proto.gemspec +33 -0
- data/examples/addressbook.bin +0 -0
- data/examples/addressbook.capnp +31 -0
- data/examples/create_test_data.py +39 -0
- data/examples/example.rb +38 -0
- data/ext/capn_proto/.ycm_extra_conf.py +65 -0
- data/ext/capn_proto/.ycm_extra_conf.pyc +0 -0
- data/ext/capn_proto/class_builder.cc +80 -0
- data/ext/capn_proto/class_builder.h +72 -0
- data/ext/capn_proto/dynamic_list_reader.cc +52 -0
- data/ext/capn_proto/dynamic_list_reader.h +23 -0
- data/ext/capn_proto/dynamic_struct_reader.cc +59 -0
- data/ext/capn_proto/dynamic_struct_reader.h +23 -0
- data/ext/capn_proto/dynamic_value_reader.cc +50 -0
- data/ext/capn_proto/dynamic_value_reader.h +13 -0
- data/ext/capn_proto/exception.cc +24 -0
- data/ext/capn_proto/exception.h +18 -0
- data/ext/capn_proto/extconf.rb +29 -0
- data/ext/capn_proto/field_list.cc +51 -0
- data/ext/capn_proto/field_list.h +23 -0
- data/ext/capn_proto/init.cc +34 -0
- data/ext/capn_proto/list_nested_node_reader.cc +50 -0
- data/ext/capn_proto/list_nested_node_reader.h +24 -0
- data/ext/capn_proto/message_reader.cc +30 -0
- data/ext/capn_proto/message_reader.h +17 -0
- data/ext/capn_proto/nested_node_reader.cc +42 -0
- data/ext/capn_proto/nested_node_reader.h +21 -0
- data/ext/capn_proto/parsed_schema.cc +58 -0
- data/ext/capn_proto/parsed_schema.h +23 -0
- data/ext/capn_proto/rb.cc +0 -0
- data/ext/capn_proto/rb.h +0 -0
- data/ext/capn_proto/ruby_capn_proto.cc +4 -0
- data/ext/capn_proto/ruby_capn_proto.h +38 -0
- data/ext/capn_proto/schema_node_reader.cc +51 -0
- data/ext/capn_proto/schema_node_reader.h +22 -0
- data/ext/capn_proto/schema_parser.cc +53 -0
- data/ext/capn_proto/schema_parser.h +20 -0
- data/ext/capn_proto/stream_fd_message_reader.cc +53 -0
- data/ext/capn_proto/stream_fd_message_reader.h +21 -0
- data/ext/capn_proto/struct_schema.cc +57 -0
- data/ext/capn_proto/struct_schema.h +23 -0
- data/ext/capn_proto/util.cc +25 -0
- data/ext/capn_proto/util.h +16 -0
- data/lib/capn_proto/version.rb +3 -0
- data/lib/capn_proto.rb +88 -0
- data/media/captain_proto.png +0 -0
- data/media/captain_proto_small.png +0 -0
- data/spec/addressbook.bin +0 -0
- data/spec/addressbook.capnp +31 -0
- data/spec/capn_proto_spec.rb +7 -0
- data/spec/create_test_data.py +38 -0
- metadata +188 -0
data/Gemfile
ADDED
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
|
data/capn_proto.gemspec
ADDED
@@ -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)
|
data/examples/example.rb
ADDED
@@ -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
|
+
}
|