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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 72e98b82d68080ed07cff8821dc4a1416bc3a9f4
4
- data.tar.gz: 99c9cfbfd0952ce27307a538c2983f2e8a0831f0
3
+ metadata.gz: 524d81700b2d1815f92ece4273209b6f45810944
4
+ data.tar.gz: ac5b8b07b2e7084fc8f2ff7c5788215106681423
5
5
  SHA512:
6
- metadata.gz: d7e39fb6fa4221c4bc220612b6b1b65e9f572e19723dfb83dcff4d51d3caa75c86dd667dc9570b506cf386115280a1ce7154c313a8f67aaf37d74cdde468b622
7
- data.tar.gz: 5f03642c8f5505fa28a2a950e4706b59333e840cf3fa274511de0aef460fecc3e2f120b4bce89af9183e151ed628384bbbc5ba487d8e0c5611d36bfca37f290c
6
+ metadata.gz: 6ffd0d3137cdd3334fc547de1b1a882937bcbaa2c54483be4e9ad832a02a4416980690e02da5f178cd69269217cdfd4efd0c2f15a1dfb0afd129b673fe5250e0
7
+ data.tar.gz: bacc20d6e15f56bc2d17474bbdab5ed299425db510a13236d0682402cbf09f9d5bd5211a451dafdf68d1e7b9056c56a8a0c5da97711f65650e1d1a6e7167a758
@@ -1,16 +1,24 @@
1
1
  language: ruby
2
2
  rvm:
3
- - jruby
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
- - wget https://github.com/PJK/libcbor/archive/master.zip
11
- - unzip master.zip
12
- - cd libcbor-master
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 ..
@@ -0,0 +1 @@
1
+ yardoc lib/**/*rb -M redcarpet
data/README.md CHANGED
@@ -1,11 +1,21 @@
1
1
  # libcbor
2
2
 
3
- The Ruby bindings for [libcbor](https://github.com/PJK/libcbor)
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` is present on your system.
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`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
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.
@@ -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
- # require "pry"
11
- # Pry.start
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
+ ��������
@@ -8,4 +8,4 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..'))
8
8
  require 'lib/libcbor'
9
9
  require 'pp'
10
10
 
11
- ARGV.each { |_| PP.pp CBOR.decode(IO.read(_)) }
11
+ ARGV.each { |_| PP.pp CBOR.decode(IO.read(_)) }
@@ -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
@@ -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/cbor_item'
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
- def self.encode(obj)
21
- obj.to_cbor
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
- def method_name
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
- const_get(klass).send(:include, const_get('::CBOR::' + klass + 'Helper'))
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
- CBORItem.new(
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
@@ -0,0 +1,5 @@
1
+ # Convenience include helper. Enables
2
+ # require 'libcbor/all'
3
+
4
+ require 'libcbor'
5
+ CBOR.load!
@@ -0,0 +1,5 @@
1
+ module CBOR
2
+ # Represents CBOR byte strings, as opposed to default string
3
+ class ByteString < ::String
4
+ end
5
+ end
@@ -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
@@ -1,6 +1,10 @@
1
1
  module CBOR
2
+ # Provides the {#to_cbor} (or equivalent) method for Fixnums
2
3
  module FixnumHelper
3
- def to_cbor
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
- def to_cbor
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
- def to_cbor
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
- def to_cbor
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.to_cbor
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
- def to_cbor
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.to_cbor
51
- header += member.last.to_cbor
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
- def to_cbor
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.to_cbor
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
- def to_cbor
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
- def to_cbor
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
- def to_cbor
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
@@ -1,4 +1,4 @@
1
- # Provides
1
+ # Provides native memory management
2
2
  module CBOR::LibC
3
3
  extend FFI::Library
4
4
  ffi_lib FFI::Library::LIBC
@@ -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
@@ -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
@@ -0,0 +1,10 @@
1
+ module CBOR
2
+ # Represents Simple value other than those that have native Ruby mapping
3
+ class SimpleValue < Struct.new(:value)
4
+ def ==(other)
5
+ if other.is_a? SimpleValue
6
+ other.value == value
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,5 @@
1
+ module CBOR
2
+ # Provides streaming encoding and decoding utilities
3
+ module Streaming
4
+ end
5
+ 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
- read = LibCBOR.cbor_stream_decode(
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
- )[:read]
35
- break if read == 0
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
- class Encoder < Struct.new(:target)
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
- target.write(object.to_cbor)
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
- target.write("\x9f")
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
- target.write("\xbf")
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
- target.write("\x9f")
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
- target.write("\x5f")
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
- @@bfr.get_bytes(0, LibCBOR.cbor_encode_tag(value, @@bfr, 9))
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
- target.write("\xff")
71
+ stream.write("\xff")
31
72
  end
73
+
74
+ protected
75
+
76
+ attr_accessor :stream
32
77
  end
33
78
  end
34
79
  end
@@ -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
@@ -1,3 +1,4 @@
1
1
  module CBOR
2
- VERSION = "0.1.0-alpha"
2
+ # The current version. It is completely independent of libcbor's version
3
+ VERSION = '0.1.0'
3
4
  end
@@ -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 = ["PJK"]
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.8"
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.pre.alpha
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
- - PJK
7
+ - Pavel Kalvoda
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-05-09 00:00:00.000000000 Z
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.8'
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.8'
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/inner/prealloc.rb
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: 1.3.1
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:
@@ -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
@@ -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
@@ -1,10 +0,0 @@
1
- # Provides a fixed, pre-allocated pool of common data items
2
- # that can be used for quickly encoding atomic values without
3
- # the need for allocation
4
- module CBOR
5
- class Prealloc
6
- def initialize
7
-
8
- end
9
- end
10
- end