libcbor 0.1.0.pre.alpha → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +14 -6
- data/.yardopts +1 -0
- data/README.md +104 -3
- data/bin/console +3 -5
- data/examples/converter.rb +38 -0
- data/examples/data/indef_array.cbor +1 -0
- data/examples/load_file.rb +1 -1
- data/examples/network_streaming.rb +49 -0
- data/lib/libcbor.rb +34 -8
- data/lib/libcbor/all.rb +5 -0
- data/lib/libcbor/byte_string.rb +5 -0
- data/lib/libcbor/cache.rb +16 -0
- data/lib/libcbor/helpers.rb +76 -13
- data/lib/libcbor/inner/lib_c.rb +1 -1
- data/lib/libcbor/inner/lib_cbor.rb +23 -2
- data/lib/libcbor/item.rb +119 -0
- data/lib/libcbor/simple_value.rb +10 -0
- data/lib/libcbor/streaming.rb +5 -0
- data/lib/libcbor/streaming/buffered_decoder.rb +47 -3
- data/lib/libcbor/streaming/callback_simplifier.rb +5 -0
- data/lib/libcbor/streaming/encoder.rb +53 -8
- data/lib/libcbor/tag.rb +9 -0
- data/lib/libcbor/version.rb +2 -1
- data/libcbor.gemspec +6 -2
- metadata +73 -10
- data/lib/libcbor/cbor_item.rb +0 -64
- data/lib/libcbor/inner.rb +0 -28
- data/lib/libcbor/inner/prealloc.rb +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 524d81700b2d1815f92ece4273209b6f45810944
|
4
|
+
data.tar.gz: ac5b8b07b2e7084fc8f2ff7c5788215106681423
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6ffd0d3137cdd3334fc547de1b1a882937bcbaa2c54483be4e9ad832a02a4416980690e02da5f178cd69269217cdfd4efd0c2f15a1dfb0afd129b673fe5250e0
|
7
|
+
data.tar.gz: bacc20d6e15f56bc2d17474bbdab5ed299425db510a13236d0682402cbf09f9d5bd5211a451dafdf68d1e7b9056c56a8a0c5da97711f65650e1d1a6e7167a758
|
data/.travis.yml
CHANGED
@@ -1,16 +1,24 @@
|
|
1
1
|
language: ruby
|
2
2
|
rvm:
|
3
|
-
-
|
4
|
-
- rbx-2.1.1
|
3
|
+
#- rbx-2.1.1
|
5
4
|
- 2.0.0
|
6
5
|
- 2.1.1
|
7
6
|
- 2.2.1
|
8
7
|
script: bundle exec rspec spec
|
9
8
|
before_install:
|
10
|
-
-
|
11
|
-
-
|
12
|
-
-
|
9
|
+
- sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
|
10
|
+
- sudo apt-get update -qq
|
11
|
+
- sudo apt-get -qq install gcc-4.9
|
12
|
+
- sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 90
|
13
|
+
- git clone https://github.com/PJK/libcbor.git
|
14
|
+
- cd libcbor
|
15
|
+
- git submodule update --init test/cmocka
|
16
|
+
- cd test
|
17
|
+
- mkdir cmocka_build && cd cmocka_build
|
18
|
+
- cmake ../cmocka
|
19
|
+
- make -j 4
|
20
|
+
- sudo make install
|
21
|
+
- cd ../..
|
13
22
|
- cmake .
|
14
|
-
- make cbor cbor_shared
|
15
23
|
- sudo make install
|
16
24
|
- cd ..
|
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
yardoc lib/**/*rb -M redcarpet
|
data/README.md
CHANGED
@@ -1,11 +1,21 @@
|
|
1
1
|
# libcbor
|
2
2
|
|
3
|
-
|
3
|
+
[![Build Status](https://travis-ci.org/PJK/libcbor-ruby.svg?branch=master)](https://travis-ci.org/PJK/libcbor-ruby)
|
4
|
+
[![Coverage Status](https://coveralls.io/repos/PJK/libcbor-ruby/badge.svg?branch=master)](https://coveralls.io/r/PJK/libcbor-ruby?branch=master)
|
4
5
|
|
6
|
+
The Ruby bindings for [libcbor](https://github.com/PJK/libcbor). Provides [CBOR](http://cbor.io/)
|
7
|
+
encoding and decoding features, including streaming.
|
8
|
+
|
9
|
+
## Important resources
|
10
|
+
|
11
|
+
- [libcbor](http://libcbor.org/)
|
12
|
+
- [API reference](http://www.rubydoc.info/gems/libcbor/)
|
13
|
+
- [git repository](https://github.com/PJK/libcbor-ruby)
|
14
|
+
- [rubygems.org page](https://rubygems.org/gems/libcbor)
|
5
15
|
|
6
16
|
## Installation
|
7
17
|
|
8
|
-
Make sure that `libffi-dev`
|
18
|
+
Make sure that `libffi-dev` and `libcbor` are present on your system.
|
9
19
|
|
10
20
|
Add this line to your application's Gemfile:
|
11
21
|
|
@@ -23,12 +33,90 @@ Or install it yourself as:
|
|
23
33
|
|
24
34
|
## Usage
|
25
35
|
|
36
|
+
Include the library using
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
include 'libcbor/all'
|
40
|
+
```
|
41
|
+
|
42
|
+
You can then encode objects
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
{ 'key' => 42 }.to_cbor
|
46
|
+
# => "\xA1ckey\x18*"
|
47
|
+
```
|
48
|
+
|
49
|
+
... as well as decode serialized data
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
CBOR.decode("\xA1ckey\x18*")
|
53
|
+
# => {"key"=>42}
|
54
|
+
```
|
55
|
+
|
56
|
+
*libcbor* also comes with streaming features. When decoding, you can specify
|
57
|
+
callbacks and handle the input as desired. The following example illustrates
|
58
|
+
how to integrate *libcbor* with [EventMachine](https://github.com/eventmachine/eventmachine):
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
#!/usr/bin/env ruby
|
62
|
+
|
63
|
+
# Listens for connections, asynchronously receives data, replies with
|
64
|
+
# pretty-printed arrays (works for indefinite arrays with integers only for
|
65
|
+
# the sake of simplicity)
|
66
|
+
#
|
67
|
+
# Make sure to install EventMachine first (`$ gem install eventmachine`)
|
68
|
+
#
|
69
|
+
# Start with
|
70
|
+
# $ ./examples/network_streaming.rb
|
71
|
+
#
|
72
|
+
# Then send data from the example file using netcat or a similar tool:
|
73
|
+
# $ netcat localhost 9000 < examples/data/indef_array.cbor
|
74
|
+
#
|
75
|
+
# The file from the example contains the CBOR representation of
|
76
|
+
# [_ [_ 1, 2], 3, [_ 4, [_ 5]]]
|
77
|
+
# Terminate with ^c
|
78
|
+
|
79
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..'))
|
80
|
+
require 'lib/libcbor'
|
81
|
+
require 'rubygems'
|
82
|
+
require 'eventmachine'
|
83
|
+
|
84
|
+
class CBORPrinter < EM::Connection
|
85
|
+
def print(what)
|
86
|
+
send_data(' ' * @nesting + what.to_s + "\n")
|
87
|
+
end
|
88
|
+
|
89
|
+
def initialize
|
90
|
+
@nesting = 0
|
91
|
+
@reader = CBOR::Streaming::BufferedDecoder.new(
|
92
|
+
array_start: ->() { print '['; @nesting += 1 },
|
93
|
+
integer: ->(val) { print val },
|
94
|
+
break: ->() {
|
95
|
+
@nesting -= 1; print ']'
|
96
|
+
close_connection_after_writing if @nesting == 0
|
97
|
+
}
|
98
|
+
)
|
99
|
+
end
|
100
|
+
|
101
|
+
def receive_data(data)
|
102
|
+
@reader << data
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
EventMachine.run do
|
107
|
+
Signal.trap('INT') { EventMachine.stop }
|
108
|
+
EventMachine.start_server('0.0.0.0', 9000, CBORPrinter)
|
109
|
+
end
|
110
|
+
```
|
111
|
+
|
112
|
+
Streaming encoding is possible as well. Check out the `examples` directory and the
|
113
|
+
[documentation]() for more examples.
|
26
114
|
|
27
115
|
## Development
|
28
116
|
|
29
117
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
|
30
118
|
|
31
|
-
To install this gem onto your local machine, run `bundle exec rake install`.
|
119
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
32
120
|
|
33
121
|
## Contributing
|
34
122
|
|
@@ -37,3 +125,16 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
37
125
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
38
126
|
4. Push to the branch (`git push origin my-new-feature`)
|
39
127
|
5. Create a new Pull Request
|
128
|
+
|
129
|
+
|
130
|
+
## License
|
131
|
+
|
132
|
+
The MIT License (MIT)
|
133
|
+
|
134
|
+
Copyright (c) Pavel Kalvoda, 2015
|
135
|
+
|
136
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
137
|
+
|
138
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
139
|
+
|
140
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/bin/console
CHANGED
@@ -1,14 +1,12 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require "bundler/setup"
|
4
|
-
require "libcbor"
|
4
|
+
require "libcbor/all"
|
5
5
|
|
6
6
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
7
|
# with your gem easier. You can also use a different console, if you like.
|
8
8
|
|
9
9
|
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
-
|
11
|
-
|
10
|
+
require "pry"
|
11
|
+
Pry.start
|
12
12
|
|
13
|
-
require "irb"
|
14
|
-
IRB.start
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# CBOR <-> JSON converter. Works for compatible constructs only.
|
4
|
+
# Make sure to install trollop (`$ gem install trollop`) before using this.
|
5
|
+
#
|
6
|
+
# Usage:
|
7
|
+
# $ cat examples/data/indef_array.cbor | ./examples/converter.rb | ./examples/converter.rb --to-cbor | ./examples/converter.rb
|
8
|
+
|
9
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..'))
|
10
|
+
require 'lib/libcbor/all'
|
11
|
+
require 'trollop'
|
12
|
+
require 'json'
|
13
|
+
|
14
|
+
opts = Trollop::options do
|
15
|
+
banner <<-EOS
|
16
|
+
Converts between JSON and CBOR. Uses STDIN and STDOUT for I/O
|
17
|
+
|
18
|
+
Usage:
|
19
|
+
converter [options]
|
20
|
+
|
21
|
+
where [options] are:
|
22
|
+
EOS
|
23
|
+
|
24
|
+
opt :to_json,
|
25
|
+
'Convert from CBOR to JSON. Otherwise, convert from JSON to CBOR',
|
26
|
+
default: true
|
27
|
+
opt :to_cbor,
|
28
|
+
'Convert from JSON to CBOR',
|
29
|
+
default: false
|
30
|
+
end
|
31
|
+
opts[:to_json] = !opts[:to_cbor]
|
32
|
+
|
33
|
+
if opts[:to_json]
|
34
|
+
puts CBOR.decode($stdin.read).to_json
|
35
|
+
else
|
36
|
+
print CBOR.encode(JSON.load($stdin.read))
|
37
|
+
end
|
38
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
��������
|
data/examples/load_file.rb
CHANGED
@@ -0,0 +1,49 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Listens for connections, asynchronously receives data, replies with
|
4
|
+
# pretty-printed arrays (works for indefinite arrays with integers only for
|
5
|
+
# the sake of simplicity)
|
6
|
+
#
|
7
|
+
# Make sure to install EventMachine first (`$ gem install eventmachine`)
|
8
|
+
#
|
9
|
+
# Start with
|
10
|
+
# $ ./examples/network_streaming.rb
|
11
|
+
#
|
12
|
+
# Then send data from the example file using netcat or a similar tool:
|
13
|
+
# $ netcat localhost 9000 < examples/data/indef_array.cbor
|
14
|
+
#
|
15
|
+
# The file from the example contains the CBOR representation of
|
16
|
+
# [_ [_ 1, 2], 3, [_ 4, [_ 5]]]
|
17
|
+
# Terminate with ^c
|
18
|
+
|
19
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..'))
|
20
|
+
require 'lib/libcbor'
|
21
|
+
require 'rubygems'
|
22
|
+
require 'eventmachine'
|
23
|
+
|
24
|
+
class CBORPrinter < EM::Connection
|
25
|
+
def print(what)
|
26
|
+
send_data(' ' * @nesting + what.to_s + "\n")
|
27
|
+
end
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
@nesting = 0
|
31
|
+
@reader = CBOR::Streaming::BufferedDecoder.new(
|
32
|
+
array_start: ->() { print '['; @nesting += 1 },
|
33
|
+
integer: ->(val) { print val },
|
34
|
+
break: ->() {
|
35
|
+
@nesting -= 1; print ']'
|
36
|
+
close_connection_after_writing if @nesting == 0
|
37
|
+
}
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
41
|
+
def receive_data(data)
|
42
|
+
@reader << data
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
EventMachine.run do
|
47
|
+
Signal.trap('INT') { EventMachine.stop }
|
48
|
+
EventMachine.start_server('0.0.0.0', 9000, CBORPrinter)
|
49
|
+
end
|
data/lib/libcbor.rb
CHANGED
@@ -8,33 +8,59 @@ require 'libcbor/inner/lib_cbor'
|
|
8
8
|
require 'libcbor/inner/lib_c'
|
9
9
|
require 'libcbor/cache'
|
10
10
|
require 'libcbor/tag'
|
11
|
+
require 'libcbor/simple_value'
|
12
|
+
require 'libcbor/byte_string'
|
11
13
|
require 'libcbor/helpers'
|
12
|
-
require 'libcbor/
|
14
|
+
require 'libcbor/item'
|
15
|
+
require 'libcbor/streaming'
|
13
16
|
require 'libcbor/streaming/callback_simplifier'
|
14
17
|
require 'libcbor/streaming/buffered_decoder'
|
15
18
|
require 'libcbor/streaming/encoder'
|
16
19
|
|
20
|
+
# Provides encoding, decoding, and streaming interaction with CBOR data.
|
21
|
+
# Please refer to {file:README.md} for an overview and a short tutorial.
|
17
22
|
module CBOR
|
23
|
+
# Thrown when the decoded data is either invalid or not well-formed
|
18
24
|
class DecodingError < StandardError; end
|
19
25
|
|
20
|
-
|
21
|
-
|
26
|
+
# Encodes the given object to CBOR representation
|
27
|
+
# Custom semantics are supported - the object has to to provide the +to_cbor+ method
|
28
|
+
# In case {CBOR.method_name} is not +to_cbor+, provide the custom method instead.
|
29
|
+
#
|
30
|
+
# @param [Fixnum, String, Float, Array, Map, Tag, TrueClass, FalseClass, NilClass, #to_cbor] object the object to encode
|
31
|
+
# @return [String] the CBOR representation
|
32
|
+
def self.encode(object)
|
33
|
+
object.to_cbor
|
22
34
|
end
|
23
35
|
|
24
|
-
|
36
|
+
# The name of the method that is used for encoding objects. Defaults to +:to_cbor+
|
37
|
+
#
|
38
|
+
# @return [Symbol] the method name
|
39
|
+
def self.method_name
|
25
40
|
@@method_name
|
26
41
|
end
|
27
42
|
|
43
|
+
# Load the extensions for the core classes
|
44
|
+
#
|
45
|
+
# @param [Symbol] name the name to use for the encoding method. If not provided, +to_cbor+ will be used
|
46
|
+
# @return [Array] list of the patched classes
|
28
47
|
def self.load!(name = nil)
|
29
|
-
@@method_name = name
|
30
|
-
%w{Fixnum Float Array Hash String TrueClass FalseClass NilClass Tag}.each do |klass|
|
31
|
-
|
48
|
+
@@method_name = name || :to_cbor
|
49
|
+
%w{Fixnum Float Array Hash String TrueClass FalseClass NilClass Tag ByteString}.each do |klass|
|
50
|
+
kklass = const_get(klass)
|
51
|
+
kklass.send(:include, const_get('::CBOR::' + klass + 'Helper'))
|
52
|
+
kklass.send(:alias_method, method_name, :__libcbor_to_cbor)
|
32
53
|
end
|
33
54
|
end
|
34
55
|
|
56
|
+
# Deserialize CBOR
|
57
|
+
#
|
58
|
+
# @param [String] data
|
59
|
+
# @return [Fixnum, String, Float, Array, Map, Tag, TrueClass, FalseClass, NilClass] resulting object
|
60
|
+
# @raise [DecodingError] when presented with invalid data
|
35
61
|
def self.decode(data)
|
36
62
|
res = FFI::MemoryPointer.new LibCBOR::CborLoadResult
|
37
|
-
|
63
|
+
Item.new(
|
38
64
|
LibCBOR.cbor_load(FFI::MemoryPointer.from_string(data), data.bytes.count, res).
|
39
65
|
tap { |ptr| raise DecodingError if ptr.null? }
|
40
66
|
).value
|
data/lib/libcbor/all.rb
ADDED
data/lib/libcbor/cache.rb
CHANGED
@@ -3,22 +3,38 @@ module CBOR
|
|
3
3
|
class Cache
|
4
4
|
@@bfr = FFI::Buffer.new(:uchar, 1)
|
5
5
|
|
6
|
+
# Returns encoded equivalent
|
7
|
+
#
|
8
|
+
# @param [Bool] +true+ or +false+
|
9
|
+
# @return [String] The CBOR equivalent
|
6
10
|
def self.get_bool(val)
|
7
11
|
@@bfr.get_bytes(0, LibCBOR.cbor_encode_bool(val, @@bfr, 1))
|
8
12
|
end
|
9
13
|
|
14
|
+
# Returns encoded null (+nil+) equivalent
|
15
|
+
#
|
16
|
+
# @return [String] The CBOR equivalent
|
10
17
|
def self.get_null
|
11
18
|
@@bfr.get_bytes(0, LibCBOR.cbor_encode_null(@@bfr, 1))
|
12
19
|
end
|
13
20
|
|
21
|
+
# Returns cached encoded +true+ equivalent
|
22
|
+
#
|
23
|
+
# @return [String] The CBOR equivalent
|
14
24
|
def self.true
|
15
25
|
@@true ||= get_bool(true)
|
16
26
|
end
|
17
27
|
|
28
|
+
# Returns cached encoded +false+ equivalent
|
29
|
+
#
|
30
|
+
# @return [String] The CBOR equivalent
|
18
31
|
def self.false
|
19
32
|
@@false ||= get_bool(false)
|
20
33
|
end
|
21
34
|
|
35
|
+
# Returns cached encoded +nil+ equivalent
|
36
|
+
#
|
37
|
+
# @return [String] The CBOR equivalent
|
22
38
|
def self.nil
|
23
39
|
@@null ||= get_null
|
24
40
|
end
|
data/lib/libcbor/helpers.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
module CBOR
|
2
|
+
# Provides the {#to_cbor} (or equivalent) method for Fixnums
|
2
3
|
module FixnumHelper
|
3
|
-
|
4
|
+
# Encodes Fixnums. Width and signedness are handled automatically.
|
5
|
+
#
|
6
|
+
# @return [String] The CBOR representation
|
7
|
+
def __libcbor_to_cbor
|
4
8
|
@@bfr ||= FFI::Buffer.new(:uchar, 9)
|
5
9
|
if self >= 0
|
6
10
|
@@bfr.get_bytes(0, LibCBOR.cbor_encode_uint(self, @@bfr, 9))
|
@@ -10,15 +14,26 @@ module CBOR
|
|
10
14
|
end
|
11
15
|
end
|
12
16
|
|
17
|
+
# Provides the {#to_cbor} (or equivalent) method for Floats
|
13
18
|
module FloatHelper
|
14
|
-
|
19
|
+
# Encodes Floatss. Width and precision are handled automatically
|
20
|
+
#
|
21
|
+
# @return [String] The CBOR representation
|
22
|
+
def __libcbor_to_cbor
|
15
23
|
@@bfr ||= FFI::Buffer.new(:uchar, 9)
|
16
24
|
@@bfr.get_bytes(0, LibCBOR.cbor_encode_single(self, @@bfr, 9))
|
17
25
|
end
|
18
26
|
end
|
19
27
|
|
28
|
+
# Provides the {#to_cbor} (or equivalent) method for Stringss
|
20
29
|
module StringHelper
|
21
|
-
|
30
|
+
# Encodes Strings. The result is always a definite string.
|
31
|
+
#
|
32
|
+
# The string is assumed to be a valid UTF-8 string. The precondition
|
33
|
+
# is not verified.
|
34
|
+
#
|
35
|
+
# @return [String] The CBOR representation
|
36
|
+
def __libcbor_to_cbor
|
22
37
|
@@item ||= LibCBOR.cbor_new_definite_string
|
23
38
|
string = FFI::MemoryPointer.from_string(self)
|
24
39
|
out_bfr = FFI::MemoryPointer.new :pointer
|
@@ -31,51 +46,99 @@ module CBOR
|
|
31
46
|
end
|
32
47
|
end
|
33
48
|
|
49
|
+
|
50
|
+
module ByteStringHelper
|
51
|
+
# Encodes {ByteString}s. The result is always a definite string.
|
52
|
+
#
|
53
|
+
# @return [String] The CBOR representation
|
54
|
+
def __libcbor_to_cbor
|
55
|
+
@@item ||= LibCBOR.cbor_new_definite_bytestring
|
56
|
+
string = FFI::MemoryPointer.from_string(self)
|
57
|
+
out_bfr = FFI::MemoryPointer.new :pointer
|
58
|
+
out_bfr_len = FFI::MemoryPointer.new :size_t
|
59
|
+
LibCBOR.cbor_bytestring_set_handle(@@item, string, bytes.length)
|
60
|
+
res_len = LibCBOR.cbor_serialize_alloc(@@item, out_bfr, out_bfr_len)
|
61
|
+
out_bfr.read_pointer.get_bytes(0, res_len).tap do
|
62
|
+
LibC.free(out_bfr.read_pointer)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Provides the {#to_cbor} (or equivalent) method for Arrayss
|
34
68
|
module ArrayHelper
|
35
|
-
|
69
|
+
# Encodes Arrayss. The resulting item is always a definite array.
|
70
|
+
#
|
71
|
+
# The members are encoded recursively using the +to_cbor+ method or its equivalent
|
72
|
+
#
|
73
|
+
# @return [String] The CBOR representation
|
74
|
+
def __libcbor_to_cbor
|
36
75
|
@@bfr ||= FFI::Buffer.new(:uchar, 9)
|
37
76
|
header = @@bfr.get_bytes(0, LibCBOR.cbor_encode_array_start(count, @@bfr, 9))
|
38
77
|
each do |member|
|
39
|
-
header += member.
|
78
|
+
header += member.public_send(CBOR.method_name)
|
40
79
|
end
|
41
80
|
header
|
42
81
|
end
|
43
82
|
end
|
44
83
|
|
84
|
+
# Provides the {#to_cbor} (or equivalent) method for Hashes
|
45
85
|
module HashHelper
|
46
|
-
|
86
|
+
# Encodes Hashes. The resulting item is always a definite map.
|
87
|
+
#
|
88
|
+
# The members are encoded recursively using the +to_cbor+ method or its equivalent
|
89
|
+
#
|
90
|
+
# @return [String] The CBOR representation
|
91
|
+
def __libcbor_to_cbor
|
47
92
|
@@bfr ||= FFI::Buffer.new(:uchar, 9)
|
48
93
|
header = @@bfr.get_bytes(0, LibCBOR.cbor_encode_map_start(count, @@bfr, 9))
|
49
94
|
each do |member|
|
50
|
-
header += member.first.
|
51
|
-
header += member.last.
|
95
|
+
header += member.first.public_send(CBOR.method_name)
|
96
|
+
header += member.last.public_send(CBOR.method_name)
|
52
97
|
end
|
53
98
|
header
|
54
99
|
end
|
55
100
|
end
|
56
101
|
|
102
|
+
# Provides the {#to_cbor} (or equivalent) method for Tags
|
57
103
|
module TagHelper
|
58
|
-
|
104
|
+
# Encodes Tags.
|
105
|
+
#
|
106
|
+
# The {Tag#item} is encoded recursively using the +to_cbor+ method or its equivalent
|
107
|
+
#
|
108
|
+
# @return [String] The CBOR representation
|
109
|
+
def __libcbor_to_cbor
|
59
110
|
@@bfr ||= FFI::Buffer.new(:uchar, 9)
|
60
111
|
header = @@bfr.get_bytes(0, LibCBOR.cbor_encode_tag(value, @@bfr, 9))
|
61
|
-
header + item.
|
112
|
+
header + item.public_send(CBOR.method_name)
|
62
113
|
end
|
63
114
|
end
|
64
115
|
|
116
|
+
# Provides the {#to_cbor} (or equivalent) method for +true+
|
65
117
|
module TrueClassHelper
|
66
|
-
|
118
|
+
# Encodes +true+s.
|
119
|
+
#
|
120
|
+
# @return [String] The CBOR representation
|
121
|
+
def __libcbor_to_cbor
|
67
122
|
Cache.true
|
68
123
|
end
|
69
124
|
end
|
70
125
|
|
126
|
+
# Provides the {#to_cbor} (or equivalent) method for +false+
|
71
127
|
module FalseClassHelper
|
72
|
-
|
128
|
+
# Encodes +false+s.
|
129
|
+
#
|
130
|
+
# @return [String] The CBOR representation
|
131
|
+
def __libcbor_to_cbor
|
73
132
|
Cache.false
|
74
133
|
end
|
75
134
|
end
|
76
135
|
|
136
|
+
# Provides the {#to_cbor} (or equivalent) method for +nil+
|
77
137
|
module NilClassHelper
|
78
|
-
|
138
|
+
# Encodes +nil+s.
|
139
|
+
#
|
140
|
+
# @return [String] The CBOR representation
|
141
|
+
def __libcbor_to_cbor
|
79
142
|
Cache.nil
|
80
143
|
end
|
81
144
|
end
|
data/lib/libcbor/inner/lib_c.rb
CHANGED
@@ -1,25 +1,36 @@
|
|
1
1
|
module CBOR
|
2
|
+
# Provides low-level binding for the native functions
|
2
3
|
module LibCBOR
|
3
4
|
extend FFI::Library
|
4
|
-
ffi_lib 'cbor'
|
5
|
+
ffi_lib ['cbor', 'libcbor.so.1', '/usr/local/lib/libcbor.so']
|
5
6
|
|
7
|
+
# The +cbor_item_t *+ handle type
|
6
8
|
CborItemTRef = typedef :pointer, :cbor_item_t_ref
|
9
|
+
|
10
|
+
# The CBOR types enum mapping
|
11
|
+
Type = enum(:uint, :negint, :bytestring, :string, :array, :map, :tag, :float_ctrl)
|
12
|
+
|
13
|
+
|
7
14
|
typedef :pointer, :cbor_item_t_ref_array
|
8
15
|
typedef :pointer, :buffer
|
9
16
|
typedef :pointer, :memblock # unsigned char * - string & bytestring handles, raw blocks
|
10
17
|
|
18
|
+
# Possible error codes for the +cbor_error+
|
11
19
|
ErrorCode = enum(:none, :notenoughdata, :nodata, :malformated, :memerror, :syntaxerror)
|
12
20
|
|
21
|
+
# Represents +cbor_error+ decoding error
|
13
22
|
class CborError < FFI::Struct
|
14
23
|
layout :position, :size_t,
|
15
24
|
:code, ErrorCode
|
16
25
|
end
|
17
26
|
|
27
|
+
# Represents +cbor_load_result+ struct
|
18
28
|
class CborLoadResult < FFI::Struct
|
19
29
|
layout :error, CborError,
|
20
30
|
:read, :size_t
|
21
31
|
end
|
22
32
|
|
33
|
+
# Represents +cbor_pair+ for map manipualtion
|
23
34
|
class CborPair < FFI::Struct
|
24
35
|
layout :key, CborItemTRef,
|
25
36
|
:value, CborItemTRef
|
@@ -44,10 +55,11 @@ module CBOR
|
|
44
55
|
attach_function :cbor_serialize_alloc, [:pointer, :pointer, :pointer], :size_t
|
45
56
|
|
46
57
|
attach_function :cbor_new_definite_string, [], :pointer
|
58
|
+
attach_function :cbor_new_definite_bytestring, [], :pointer
|
47
59
|
# void cbor_string_set_handle(cbor_item_t *item, unsigned char *data, size_t length);
|
48
60
|
attach_function :cbor_string_set_handle, [:pointer, :pointer, :size_t], :void
|
61
|
+
attach_function :cbor_bytestring_set_handle, [:pointer, :pointer, :size_t], :void
|
49
62
|
|
50
|
-
Type = enum(:uint, :negint, :bytestring, :string, :array, :map, :tag, :float_ctrl)
|
51
63
|
|
52
64
|
attach_function :cbor_typeof, [:cbor_item_t_ref], Type
|
53
65
|
attach_function :cbor_load, [:buffer, :size_t, :cbor_load_result_ref], :cbor_item_t_ref
|
@@ -56,9 +68,15 @@ module CBOR
|
|
56
68
|
|
57
69
|
attach_function :cbor_string_length, [:cbor_item_t_ref], :size_t
|
58
70
|
attach_function :cbor_string_handle, [:cbor_item_t_ref], :memblock
|
71
|
+
attach_function :cbor_string_is_definite, [:cbor_item_t_ref], :bool
|
72
|
+
attach_function :cbor_string_chunks_handle, [:cbor_item_t_ref], :cbor_item_t_ref_array
|
73
|
+
attach_function :cbor_string_chunk_count, [:cbor_item_t_ref], :size_t
|
59
74
|
|
60
75
|
attach_function :cbor_bytestring_length, [:cbor_item_t_ref], :size_t
|
61
76
|
attach_function :cbor_bytestring_handle, [:cbor_item_t_ref], :memblock
|
77
|
+
attach_function :cbor_bytestring_is_definite, [:cbor_item_t_ref], :bool
|
78
|
+
attach_function :cbor_bytestring_chunks_handle, [:cbor_item_t_ref], :cbor_item_t_ref_array
|
79
|
+
attach_function :cbor_bytestring_chunk_count, [:cbor_item_t_ref], :size_t
|
62
80
|
|
63
81
|
attach_function :cbor_array_size, [:cbor_item_t_ref], :size_t
|
64
82
|
attach_function :cbor_array_handle, [:cbor_item_t_ref], :cbor_item_t_ref_array
|
@@ -84,6 +102,7 @@ module CBOR
|
|
84
102
|
callback :cbor_double_callback, [:pointer, :double], :void
|
85
103
|
callback :cbor_bool_callback, [:pointer, :bool], :void
|
86
104
|
|
105
|
+
# The +cbor_callbacks+ callback bundle equivalent
|
87
106
|
class CborCallbacks < FFI::Struct
|
88
107
|
layout :uint8, :cbor_int8_callback,
|
89
108
|
:uint16, :cbor_int16_callback,
|
@@ -120,8 +139,10 @@ module CBOR
|
|
120
139
|
:indef_break, :cbor_simple_callback
|
121
140
|
end
|
122
141
|
|
142
|
+
# High-level decoder status enum mapping
|
123
143
|
DecoderStatus = enum(:finished, :not_enough_data, :buffer_error, :error)
|
124
144
|
|
145
|
+
# Represents +cbor_decoder_result+ struct
|
125
146
|
class CborDecoderResult < FFI::Struct
|
126
147
|
layout :read, :size_t,
|
127
148
|
:status, DecoderStatus
|
data/lib/libcbor/item.rb
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
module CBOR
|
2
|
+
# Wraps native +cbor_item_t *+ to allow extracting Ruby objects
|
3
|
+
#
|
4
|
+
# Takes responsibility for high-level native interfacing and object
|
5
|
+
# lifetime management.
|
6
|
+
#
|
7
|
+
# @attr [FFI::Pointer] handle Native memory handle
|
8
|
+
class Item < Struct.new(:handle)
|
9
|
+
# Type of the underlying item
|
10
|
+
#
|
11
|
+
# @return [Symbol] one of {LibCBOR::Type}
|
12
|
+
def type
|
13
|
+
LibCBOR.cbor_typeof(handle)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Ruby representation of the {Item}
|
17
|
+
#
|
18
|
+
# Arrays and hash maps are constructed recursively
|
19
|
+
#
|
20
|
+
# @return [Fixnum, String, Float, Array, Map, Tag, TrueClass, FalseClass, NilClass] Value extracted from the {#handle}
|
21
|
+
def value
|
22
|
+
case type
|
23
|
+
when :uint
|
24
|
+
LibCBOR.cbor_get_int(handle)
|
25
|
+
when :negint
|
26
|
+
-LibCBOR.cbor_get_int(handle) - 1
|
27
|
+
when :string
|
28
|
+
load_string
|
29
|
+
when :bytestring
|
30
|
+
load_bytestring
|
31
|
+
when :array
|
32
|
+
LibCBOR
|
33
|
+
.cbor_array_handle(handle)
|
34
|
+
.read_array_of_type(LibCBOR::CborItemTRef, :read_pointer, LibCBOR.cbor_array_size(handle))
|
35
|
+
.map { |item| Item.new(item).value }
|
36
|
+
when :map
|
37
|
+
pairs_handle = LibCBOR.cbor_map_handle(handle)
|
38
|
+
Hash[LibCBOR.cbor_map_size(handle).times.map { |idx|
|
39
|
+
pair = LibCBOR::CborPair.new(pairs_handle + LibCBOR::CborPair.size * idx)
|
40
|
+
[pair[:key], pair[:value]].map { |ptr| Item.new(ptr).value }
|
41
|
+
}]
|
42
|
+
when :tag
|
43
|
+
Tag.new(
|
44
|
+
LibCBOR.cbor_tag_value(handle),
|
45
|
+
Item.new(LibCBOR.cbor_tag_item(handle)).value
|
46
|
+
)
|
47
|
+
when :float_ctrl
|
48
|
+
load_float
|
49
|
+
else
|
50
|
+
raise 'Unknown type - the FFI enum mapping is probably broken. Please report this bug.'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
protected
|
55
|
+
|
56
|
+
# Loads float, doesn't check the type
|
57
|
+
#
|
58
|
+
# @return [Float] the result
|
59
|
+
def load_float
|
60
|
+
if LibCBOR.cbor_float_ctrl_is_ctrl(handle)
|
61
|
+
case ctr_val = LibCBOR.cbor_ctrl_value(handle)
|
62
|
+
when 20
|
63
|
+
false
|
64
|
+
when 21
|
65
|
+
true
|
66
|
+
when 22
|
67
|
+
nil
|
68
|
+
else
|
69
|
+
SimpleValue.new(ctr_val)
|
70
|
+
end
|
71
|
+
else
|
72
|
+
LibCBOR.cbor_float_get_float(handle)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Loads string, doesn't check the type
|
77
|
+
#
|
78
|
+
# If the underlying string is indefinite, the concatenation of its chunks is returned
|
79
|
+
#
|
80
|
+
# @return [String] the result
|
81
|
+
def load_string
|
82
|
+
if LibCBOR.cbor_string_is_definite(handle)
|
83
|
+
LibCBOR
|
84
|
+
.cbor_string_handle(handle)
|
85
|
+
.get_string(0, LibCBOR.cbor_string_length(handle))
|
86
|
+
else
|
87
|
+
LibCBOR
|
88
|
+
.cbor_string_chunks_handle(handle)
|
89
|
+
.read_array_of_type(LibCBOR::CborItemTRef, :read_pointer, LibCBOR.cbor_string_chunk_count(handle))
|
90
|
+
.map { |item| Item.new(item).value }
|
91
|
+
.join
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Loads byte string, doesn't check the type
|
96
|
+
#
|
97
|
+
# If the underlying string is indefinite, the concatenation of its chunks is returned
|
98
|
+
#
|
99
|
+
# @return [String] the result
|
100
|
+
def load_bytestring
|
101
|
+
# TODO: DRY - load_string
|
102
|
+
if LibCBOR.cbor_bytestring_is_definite(handle)
|
103
|
+
ByteString.new(
|
104
|
+
LibCBOR
|
105
|
+
.cbor_bytestring_handle(handle)
|
106
|
+
.get_string(0, LibCBOR.cbor_bytestring_length(handle))
|
107
|
+
)
|
108
|
+
else
|
109
|
+
ByteString.new(
|
110
|
+
LibCBOR
|
111
|
+
.cbor_bytestring_chunks_handle(handle)
|
112
|
+
.read_array_of_type(LibCBOR::CborItemTRef, :read_pointer, LibCBOR.cbor_bytestring_chunk_count(handle))
|
113
|
+
.map { |item| Item.new(item).value }
|
114
|
+
.join
|
115
|
+
)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -1,6 +1,27 @@
|
|
1
1
|
module CBOR
|
2
2
|
module Streaming
|
3
|
+
# Decodes a stream of data and invokes the appropriate callbacks
|
4
|
+
#
|
5
|
+
# To use it, just initialize it with the desired set of callbacks and start
|
6
|
+
# feeding data to it. Please see {file:examples/network_streaming.rb} for
|
7
|
+
# an example
|
3
8
|
class BufferedDecoder
|
9
|
+
# @param [Hash] callbacks the callbacks to invoke during parsing.
|
10
|
+
# @option callbacks [Proc<Fixnum>] :integer Integers, both positive and negative
|
11
|
+
# @option callbacks [Proc<String>] :string Definite string
|
12
|
+
# @option callbacks [Proc] :chunked_string_start Chunked string. Chunks follow
|
13
|
+
# @option callbacks [Proc<String>] :byte_string Definite byte string
|
14
|
+
# @option callbacks [Proc] :chunked_byte_string_start Chunked byte string. Chunks follow
|
15
|
+
# @option callbacks [Proc<Float>] :float Float
|
16
|
+
# @option callbacks [Proc<length: Fixnum>] :definite_array Definite array
|
17
|
+
# @option callbacks [Proc] :array_start Indefinite array start
|
18
|
+
# @option callbacks [Proc<length: Fixnum>] :definite_map Definite map. Length pairs follow
|
19
|
+
# @option callbacks [Proc] :map_start Indefinite map start
|
20
|
+
# @option callbacks [Proc<value: Fixnum>] :tag Tag. Tagged item follows
|
21
|
+
# @option callbacks [Proc<Bool>] :bool Boolean
|
22
|
+
# @option callbacks [Proc] :null Null
|
23
|
+
# @option callbacks [Proc<value: Fixnum>] :simple Simple value other than +true, false, nil+
|
24
|
+
# @option callbacks [Proc] :break Indefinite item break
|
4
25
|
def initialize(callbacks = {})
|
5
26
|
@callbacks = {
|
6
27
|
integer: Proc.new {},
|
@@ -23,20 +44,43 @@ module CBOR
|
|
23
44
|
@proxy = CallbackSimplifier.new(self)
|
24
45
|
end
|
25
46
|
|
47
|
+
# Append data to the internal buffer.
|
48
|
+
#
|
49
|
+
# Parsing will ensue and all the appropriate callbacks will be invoked.
|
50
|
+
# The method will block until all the callbacks have finished.
|
51
|
+
#
|
52
|
+
# @param [String] data CBOR input data
|
53
|
+
# @return [void]
|
54
|
+
# @raise [DecodingError] if the decoder encountered a invalid input
|
26
55
|
def <<(data)
|
27
56
|
@buffer += data
|
28
57
|
loop do
|
29
|
-
|
58
|
+
result = LibCBOR.cbor_stream_decode(
|
30
59
|
FFI::MemoryPointer.from_string(@buffer),
|
31
60
|
@buffer.bytes.length,
|
32
61
|
@proxy.callback_set.to_ptr,
|
33
62
|
nil
|
34
|
-
)
|
35
|
-
|
63
|
+
)
|
64
|
+
read = result[:read]
|
65
|
+
|
66
|
+
break if read == 0 && result[:status] == :not_enough_data
|
67
|
+
|
68
|
+
unless result[:status] == :finished
|
69
|
+
raise DecodingError, "Invalid input near byte #{read} of the buffer."
|
70
|
+
end
|
71
|
+
|
36
72
|
@buffer = @buffer[read .. -1]
|
73
|
+
|
74
|
+
break if buffer.empty?
|
37
75
|
end
|
38
76
|
end
|
39
77
|
|
78
|
+
# @api private
|
79
|
+
# Invocation target for the callback proxy. Do not use.
|
80
|
+
#
|
81
|
+
# @param [Symbol] name Callback name
|
82
|
+
# @param [Array] args Arguments to pass on
|
83
|
+
# @return [void]
|
40
84
|
def callback(name, *args)
|
41
85
|
callbacks[name].call(*args)
|
42
86
|
end
|
@@ -1,7 +1,12 @@
|
|
1
1
|
module CBOR
|
2
2
|
module Streaming
|
3
|
+
# @api private
|
3
4
|
# Abstracts aways callback specifics, such as integer width
|
4
5
|
class CallbackSimplifier < Struct.new(:target)
|
6
|
+
# Returns the appropriate callback set targeting {#target}. Cached for the
|
7
|
+
# give instance.
|
8
|
+
#
|
9
|
+
# @return [LibCBOR::CborCallbacks] Callback set that enables forwarding
|
5
10
|
def callback_set
|
6
11
|
@cset ||= build_callback_set
|
7
12
|
end
|
@@ -1,34 +1,79 @@
|
|
1
1
|
module CBOR
|
2
2
|
module Streaming
|
3
|
-
|
3
|
+
# Provides streaming encoding facilities. Initialize it with an output
|
4
|
+
# object and either feed it encodable objects, or invoke the methods
|
5
|
+
# directly
|
6
|
+
class Encoder
|
7
|
+
# @param [StringIO, Socket, File, #write] stream Output object. Must support
|
8
|
+
# +write+ method that takes a +String+ as a parametr
|
9
|
+
def initialize(stream)
|
10
|
+
@stream = stream
|
11
|
+
end
|
12
|
+
|
13
|
+
# Serializes and writes an object to the stream
|
14
|
+
#
|
15
|
+
# @param [#to_cbor] object Object to serialize and write
|
16
|
+
# @return [void]
|
4
17
|
def <<(object)
|
5
|
-
|
18
|
+
stream.write(object.public_send(CBOR.method_name))
|
6
19
|
end
|
7
20
|
|
21
|
+
# Encodes a 'start array' mark. You are responsible for
|
22
|
+
# correctly {#break}ing it
|
23
|
+
#
|
24
|
+
# @return [void]
|
8
25
|
def start_array
|
9
|
-
|
26
|
+
stream.write("\x9f")
|
10
27
|
end
|
11
28
|
|
29
|
+
# Encodes a 'start map' mark. You are responsible for
|
30
|
+
# correctly {#break}ing it
|
31
|
+
#
|
32
|
+
# @return [void]
|
12
33
|
def start_map
|
13
|
-
|
34
|
+
stream.write("\xbf")
|
14
35
|
end
|
15
36
|
|
37
|
+
# Encodes a 'start indefinite string' mark. You are responsible
|
38
|
+
# for correctly {#break}ing it
|
39
|
+
#
|
40
|
+
# @return [void]
|
16
41
|
def start_chunked_string
|
17
|
-
|
42
|
+
stream.write("\x7f")
|
18
43
|
end
|
19
44
|
|
45
|
+
# Encodes a 'start indefinite byte string' mark. You are responsible
|
46
|
+
# for correctly {#break}ing it
|
47
|
+
#
|
48
|
+
# @return [void]
|
20
49
|
def start_chunked_byte_string
|
21
|
-
|
50
|
+
stream.write("\x5f")
|
22
51
|
end
|
23
52
|
|
53
|
+
# Encodes a tag with the give +value+.
|
54
|
+
#
|
55
|
+
# You are responsible for correctly supplying the item that
|
56
|
+
# follows (i.e. the one the tag will apply to)
|
57
|
+
#
|
58
|
+
# @param [Fixnum] value Tag value.
|
59
|
+
# @return [void]
|
24
60
|
def tag(value)
|
25
61
|
@@bfr ||= FFI::Buffer.new(:uchar, 9)
|
26
|
-
|
62
|
+
stream.write(
|
63
|
+
@@bfr.get_bytes(0, LibCBOR.cbor_encode_tag(value, @@bfr, 9))
|
64
|
+
)
|
27
65
|
end
|
28
66
|
|
67
|
+
# Encodes indefinite item break code.
|
68
|
+
#
|
69
|
+
# @return [void]
|
29
70
|
def break
|
30
|
-
|
71
|
+
stream.write("\xff")
|
31
72
|
end
|
73
|
+
|
74
|
+
protected
|
75
|
+
|
76
|
+
attr_accessor :stream
|
32
77
|
end
|
33
78
|
end
|
34
79
|
end
|
data/lib/libcbor/tag.rb
CHANGED
@@ -1,4 +1,13 @@
|
|
1
1
|
module CBOR
|
2
|
+
# Represents a tagged item -- a pair of number and the item
|
3
|
+
#
|
4
|
+
# @attr [Fixnum] value The tag value
|
5
|
+
# @attr [Object] item The tagged item
|
2
6
|
class Tag < Struct.new(:value, :item)
|
7
|
+
def ==(other)
|
8
|
+
if other.is_a? Tag
|
9
|
+
value == other.value && item == other.item
|
10
|
+
end
|
11
|
+
end
|
3
12
|
end
|
4
13
|
end
|
data/lib/libcbor/version.rb
CHANGED
data/libcbor.gemspec
CHANGED
@@ -6,7 +6,7 @@ require 'libcbor/version'
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "libcbor"
|
8
8
|
spec.version = CBOR::VERSION
|
9
|
-
spec.authors = ["
|
9
|
+
spec.authors = ["Pavel Kalvoda"]
|
10
10
|
spec.email = ["me@pavelkalvoda.com"]
|
11
11
|
|
12
12
|
spec.summary = %q{A Ruby binding for libcbor}
|
@@ -19,10 +19,14 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
|
22
|
-
spec.add_development_dependency "bundler", "> 1.
|
22
|
+
spec.add_development_dependency "bundler", "> 1.7"
|
23
23
|
spec.add_development_dependency "rake", "~> 10.0"
|
24
24
|
spec.add_development_dependency "rspec", "> 3"
|
25
25
|
spec.add_development_dependency "pry"
|
26
|
+
spec.add_development_dependency "yard"
|
27
|
+
spec.add_development_dependency "redcarpet"
|
28
|
+
spec.add_development_dependency "coveralls"
|
29
|
+
spec.add_development_dependency "pry-rescue"
|
26
30
|
|
27
31
|
spec.add_runtime_dependency "ffi"
|
28
32
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: libcbor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- Pavel Kalvoda
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-05-
|
11
|
+
date: 2015-05-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '>'
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '1.
|
19
|
+
version: '1.7'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '>'
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '1.
|
26
|
+
version: '1.7'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,6 +66,62 @@ dependencies:
|
|
66
66
|
- - '>='
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: yard
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: redcarpet
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: coveralls
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: pry-rescue
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
69
125
|
- !ruby/object:Gem::Dependency
|
70
126
|
name: ffi
|
71
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -92,26 +148,32 @@ files:
|
|
92
148
|
- .gitignore
|
93
149
|
- .rspec
|
94
150
|
- .travis.yml
|
151
|
+
- .yardopts
|
95
152
|
- Gemfile
|
96
153
|
- README.md
|
97
154
|
- Rakefile
|
98
155
|
- bin/console
|
99
156
|
- bin/setup
|
157
|
+
- examples/converter.rb
|
100
158
|
- examples/data/floats.cbor
|
159
|
+
- examples/data/indef_array.cbor
|
101
160
|
- examples/data/indef_string.cbor
|
102
161
|
- examples/data/integer.cbor
|
103
162
|
- examples/data/map.cbor
|
104
163
|
- examples/data/nested_array.cbor
|
105
164
|
- examples/data/tagged_date.cbor
|
106
165
|
- examples/load_file.rb
|
166
|
+
- examples/network_streaming.rb
|
107
167
|
- lib/libcbor.rb
|
168
|
+
- lib/libcbor/all.rb
|
169
|
+
- lib/libcbor/byte_string.rb
|
108
170
|
- lib/libcbor/cache.rb
|
109
|
-
- lib/libcbor/cbor_item.rb
|
110
171
|
- lib/libcbor/helpers.rb
|
111
|
-
- lib/libcbor/inner.rb
|
112
172
|
- lib/libcbor/inner/lib_c.rb
|
113
173
|
- lib/libcbor/inner/lib_cbor.rb
|
114
|
-
- lib/libcbor/
|
174
|
+
- lib/libcbor/item.rb
|
175
|
+
- lib/libcbor/simple_value.rb
|
176
|
+
- lib/libcbor/streaming.rb
|
115
177
|
- lib/libcbor/streaming/buffered_decoder.rb
|
116
178
|
- lib/libcbor/streaming/callback_simplifier.rb
|
117
179
|
- lib/libcbor/streaming/encoder.rb
|
@@ -132,9 +194,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
132
194
|
version: '0'
|
133
195
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
134
196
|
requirements:
|
135
|
-
- - '
|
197
|
+
- - '>='
|
136
198
|
- !ruby/object:Gem::Version
|
137
|
-
version:
|
199
|
+
version: '0'
|
138
200
|
requirements: []
|
139
201
|
rubyforge_project:
|
140
202
|
rubygems_version: 2.4.6
|
@@ -142,3 +204,4 @@ signing_key:
|
|
142
204
|
specification_version: 4
|
143
205
|
summary: A Ruby binding for libcbor
|
144
206
|
test_files: []
|
207
|
+
has_rdoc:
|
data/lib/libcbor/cbor_item.rb
DELETED
@@ -1,64 +0,0 @@
|
|
1
|
-
module CBOR
|
2
|
-
# Wraps native `cbor_item_t *`
|
3
|
-
class CBORItem < Struct.new(:handle)
|
4
|
-
def type
|
5
|
-
LibCBOR.cbor_typeof(handle)
|
6
|
-
end
|
7
|
-
|
8
|
-
def value
|
9
|
-
case type
|
10
|
-
when :uint
|
11
|
-
LibCBOR.cbor_get_int(handle)
|
12
|
-
when :negint
|
13
|
-
-LibCBOR.cbor_get_int(handle) - 1
|
14
|
-
when :string
|
15
|
-
LibCBOR
|
16
|
-
.cbor_string_handle(handle)
|
17
|
-
.get_string(0, LibCBOR.cbor_string_length(handle))
|
18
|
-
when :bytestring
|
19
|
-
LibCBOR
|
20
|
-
.cbor_bytestring_handle(handle)
|
21
|
-
.get_string(0, LibCBOR.cbor_bytestring_length(handle))
|
22
|
-
when :array
|
23
|
-
LibCBOR
|
24
|
-
.cbor_array_handle(handle)
|
25
|
-
.read_array_of_type(LibCBOR::CborItemTRef, :read_pointer, LibCBOR.cbor_array_size(handle))
|
26
|
-
.map { |item| CBORItem.new(item).value }
|
27
|
-
when :map
|
28
|
-
pairs_handle = LibCBOR.cbor_map_handle(handle)
|
29
|
-
Hash[LibCBOR.cbor_map_size(handle).times.map { |idx|
|
30
|
-
pair = LibCBOR::CborPair.new(pairs_handle + LibCBOR::CborPair.size * idx)
|
31
|
-
[pair[:key], pair[:value]].map { |ptr| CBORItem.new(ptr).value }
|
32
|
-
}]
|
33
|
-
when :tag
|
34
|
-
Tag.new(
|
35
|
-
LibCBOR.cbor_tag_value(handle),
|
36
|
-
CBORItem.new(LibCBOR.cbor_tag_item(handle)).value
|
37
|
-
)
|
38
|
-
when :float_ctrl
|
39
|
-
load_float
|
40
|
-
else
|
41
|
-
raise 'Unknown type - the FFI enum mapping is probably broken. Please report this bug.'
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
protected
|
46
|
-
|
47
|
-
def load_float
|
48
|
-
if LibCBOR.cbor_float_ctrl_is_ctrl(handle)
|
49
|
-
case ctr_val = LibCBOR.cbor_ctrl_value(handle)
|
50
|
-
when 20
|
51
|
-
false
|
52
|
-
when 21
|
53
|
-
true
|
54
|
-
when 22
|
55
|
-
nil
|
56
|
-
else
|
57
|
-
ctr_val
|
58
|
-
end
|
59
|
-
else
|
60
|
-
LibCBOR.cbor_float_get_float(handle)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
data/lib/libcbor/inner.rb
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
require 'ffi'
|
2
|
-
|
3
|
-
module LibC
|
4
|
-
ffi_lib FFI::Library::LIBC
|
5
|
-
extend FFI::Library
|
6
|
-
|
7
|
-
# memory allocators
|
8
|
-
attach_function :malloc, [:size_t], :pointer
|
9
|
-
attach_function :calloc, [:size_t], :pointer
|
10
|
-
attach_function :valloc, [:size_t], :pointer
|
11
|
-
attach_function :realloc, [:pointer, :size_t], :pointer
|
12
|
-
attach_function :free, [:pointer], :void
|
13
|
-
|
14
|
-
# memory movers
|
15
|
-
attach_function :memcpy, [:pointer, :pointer, :size_t], :pointer
|
16
|
-
attach_function :bcopy, [:pointer, :pointer, :size_t], :void
|
17
|
-
|
18
|
-
end # module LibC
|
19
|
-
|
20
|
-
module Libcbor
|
21
|
-
extend FFI::Library
|
22
|
-
ffi_lib 'cbor'
|
23
|
-
attach_function :cbor_new_int8, [], :pointer
|
24
|
-
attach_function :cbor_set_uint16, [:pointer, :ushort], :void
|
25
|
-
attach_function :cbor_set_uint8, [:pointer, :uchar], :void
|
26
|
-
attach_function :cbor_serialize, [:pointer, :pointer, :size_t], :size_t
|
27
|
-
puts 'yo'
|
28
|
-
end
|