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.
- 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
|
+
[](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
|
+
}
|