packable 1.3.8 → 1.3.14

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
- SHA1:
3
- metadata.gz: 9ff119e7cc22b81b365a6b56bfea0f5361cd4171
4
- data.tar.gz: 76cff9e8574909266778c4164035e54e41319439
2
+ SHA256:
3
+ metadata.gz: 010ee6e2262aa7ea8e3bccde2fa58a80afd1ba4356678c0456a638091cc50f97
4
+ data.tar.gz: 357c44f3a0252815976df5c4ac2260dabe87fb4d907546d1d8380fb37f714ae5
5
5
  SHA512:
6
- metadata.gz: 771b79907fda443f469cdbadcdc05f1740c1c0666bb55ed6cec5589d9061df758a0a4b4c7f0929adb0375422172bddd61eb2b2a11cf5654c361d67b2011ea103
7
- data.tar.gz: 1cd0a39beeb41566bc721d25ff64abe2fa7401bb0e39544893f81e3da3b91dcc4ff0e2a9c306521fd1dec6ef631e416a06fbd2cbabe35fb0cf7800ffbc9355d7
6
+ metadata.gz: 34a8168ef33d77d73dfd27156db34a95e0787900611d5c88878c07953239d80a5e4ec57002057f044ca2fcfa3879295de67206f50e730395c264f84d0cbdcacd
7
+ data.tar.gz: 8619bf57c88279a4d5a852b6a3a7810495881665da8e160ffb7bbcd7b3fc7920e18ade6f50641d19ae341be5fd65447608f06260bc9f7543231a6e7f336d9289
@@ -1,7 +1,7 @@
1
- *Note*: SciRuby are taking over maintenance for this library: https://github.com/SciRuby/packable
2
-
3
1
  = Packable Library - Intro
4
2
 
3
+ *NOTE:* This library monkeypatches core classes and wa designed for Ruby 1.8 & 1.9. A redesign using refinements would be much better. Minimal support is provided.
4
+
5
5
  If you need to do read and write binary data, there is of course <tt>Array::pack</tt> and <tt>String::unpack</tt>.
6
6
  The packable library makes (un)packing nicer, smarter and more powerful.
7
7
  In case you are wondering why on earth someone would want to do serious (un)packing when YAML & XML are built-in:
@@ -26,6 +26,7 @@ The method +each+ also accepts packing options:
26
26
  StringIO.new("\000\001\000\002\000\003").each(:short).to_a ===> [1,2,3]
27
27
  === Custom classes
28
28
  It's easy to make you own classes (un)packable. All the previous goodies are thus available:
29
+
29
30
  File.open("great_flick.flv") do |f|
30
31
  head = f.read(FLV::Header)
31
32
  f.each(FLV::Tag) do |tag|
@@ -48,7 +49,7 @@ Add GitHub to your gem sources (if you haven't already):
48
49
  Get the gem:
49
50
 
50
51
  sudo gem install marcandre-packable
51
-
52
+
52
53
  That's it! Simply <tt>require 'packable'</tt> in your code to use it.
53
54
 
54
55
  == Compatibility
@@ -97,7 +98,7 @@ When unpacking, it is necessary to specify the class in addition to any option,
97
98
 
98
99
  It's easy to add shortcuts for easier (un)packing:
99
100
 
100
- String.packers.set :flv_signature, :bytes => 3, :fill => "FLV"
101
+ String.packers.set :flv_signature, :bytes => 3, :fill => "FLV"
101
102
 
102
103
  "x".pack(:flv_signature) ===> "xFL"
103
104
 
@@ -131,14 +132,14 @@ The following shortcuts and defaults are built-in the library:
131
132
  :byte => :bytes=>1
132
133
  :unsigned_long => :bytes=>4, :signed=>false
133
134
  :unsigned_short => :bytes=>2, :signed=>false
134
-
135
- === Float
135
+
136
+ === Float
136
137
  :merge_all => :precision => :single, :endian => :big
137
138
  :default => :float
138
139
  :double => :precision => :double
139
140
  :float => {}
140
-
141
- === String
141
+
142
+ === String
142
143
  :merge_all => :fill => " "
143
144
 
144
145
  == Files and StringIO
@@ -180,7 +181,7 @@ and unpacking on +read_packed+. For example:
180
181
 
181
182
  class MyHeader < Struct.new(:signature, :nb_blocks)
182
183
  include Packable
183
-
184
+
184
185
  def write_packed(packedio, options)
185
186
  packedio << [signature, {:bytes=>3}] << [nb_blocks, :short]
186
187
  end
@@ -238,7 +239,7 @@ A final note to say that packers are inherited in some way. For instance one cou
238
239
  io.read(klass)
239
240
  end
240
241
  end
241
-
242
+
242
243
  [42, MyHeader.new("Wow", 1)].pack(:with_class, :with_class).unpack(:with_class, :with_class) ===> [42, MyHeader.new("Wow", 1)]
243
244
 
244
245
  = License
@@ -1,5 +1,6 @@
1
1
  require "packable/version"
2
- require 'backports'
2
+ require 'backports/tools/alias_method_chain'
3
+ require 'backports/rails/module'
3
4
  require_relative 'packable/packers'
4
5
  require_relative 'packable/mixin'
5
6
  [Object, Array, String, Integer, Float, IO, Proc].each do |klass|
@@ -3,7 +3,7 @@ module Packable
3
3
  module Integer #:nodoc:
4
4
  NEEDS_REVERSAL = Hash.new{|h, endian| raise ArgumentError, "Endian #{endian} is not valid. It must be one of #{h.keys.join(', ')}"}.
5
5
  merge!(:little => true, :big => false, :network => false, :native => "*\x00\x00\x00".unpack('L').first == 42).freeze
6
-
6
+
7
7
  def self.included(base)
8
8
  base.class_eval do
9
9
  include Packable
@@ -9,7 +9,26 @@ module Packable
9
9
  base.alias_method_chain :write, :packing
10
10
  base.alias_method_chain :each, :packing
11
11
  end
12
-
12
+
13
+ # Methods supported by seekable streams.
14
+ SEEKABLE_API = %i[pos pos= seek rewind].freeze
15
+
16
+ # Check whether can seek without errors.
17
+ def seekable?
18
+ if !defined?(@seekable)
19
+ @seekable =
20
+ # The IO class throws an exception at runtime if we try to change
21
+ # position on a non-regular file.
22
+ if respond_to?(:stat)
23
+ stat.file?
24
+ else
25
+ # Duck-type the rest of this.
26
+ SEEKABLE_API.all? { |m| respond_to?(m) }
27
+ end
28
+ end
29
+ @seekable
30
+ end
31
+
13
32
  # Returns the change in io.pos caused by the block.
14
33
  # Has nothing to do with packing, but quite helpful and so simple...
15
34
  def pos_change(&block)
@@ -33,11 +52,11 @@ module Packable
33
52
  r.stream = self
34
53
  r >> options
35
54
  end
36
-
55
+
37
56
  # Returns (or yields) a modified IO object that will always pack/unpack when writing/reading.
38
57
  def packed
39
58
  packedio = clone
40
- packedio.set_encoding("ascii-8bit") if packedio.respond_to? :set_encoding
59
+ packedio.set_encoding("ascii-8bit") if packedio.respond_to? :set_encoding
41
60
  class << packedio
42
61
  def << (arg)
43
62
  arg = [arg, :default] unless arg.instance_of?(::Array)
@@ -53,17 +72,17 @@ module Packable
53
72
  end
54
73
 
55
74
  def each_with_packing(*options, &block)
56
- return each_without_packing(*options, &block) if (Integer === options.first) || (String === options.first)
75
+ return each_without_packing(*options, &block) if options.empty? || (Integer === options.first) || (String === options.first) || !seekable?
57
76
  return Enumerator.new(self, :each_with_packing, *options) unless block_given?
58
77
  yield read(*options) until eof?
59
78
  end
60
79
 
61
80
  def write_with_packing(*arg)
62
- (arg.length == 1) ? write_without_packing(*arg) : pack_and_write(*arg)
81
+ (arg.length <= 1 || !seekable?) ? write_without_packing(*arg) : pack_and_write(*arg)
63
82
  end
64
-
83
+
65
84
  def read_with_packing(*arg)
66
- return read_without_packing(*arg) if arg.length == 0 || arg.first.nil? || arg.first.is_a?(Numeric)
85
+ return read_without_packing(*arg) if arg.empty? || arg.first.nil? || arg.first.is_a?(Numeric) || !seekable?
67
86
  values = Packable::Packers.to_class_option_list(*arg).map do |klass, options, original|
68
87
  if options[:read_packed]
69
88
  options[:read_packed].call(self)
@@ -73,7 +92,7 @@ module Packable
73
92
  end
74
93
  return values.size > 1 ? values : values.first
75
94
  end
76
-
95
+
77
96
  # returns a string of exactly n bytes, or else raises an EOFError
78
97
  def read_exactly(n)
79
98
  return "" if n.zero?
@@ -81,7 +100,7 @@ module Packable
81
100
  raise EOFError if s.nil? || s.length < n
82
101
  s
83
102
  end
84
-
103
+
85
104
  def pack_and_write(*arg)
86
105
  original_pos = pos
87
106
  Packable::Packers.to_object_option_list(*arg).each do |obj, options|
@@ -94,7 +113,6 @@ module Packable
94
113
  pos - original_pos
95
114
  end
96
115
 
97
-
98
116
  end
99
117
  end
100
118
  end
@@ -6,11 +6,11 @@ module Packable
6
6
  Object.send(:define_method, :__temp_bound_method, &self)
7
7
  Object.instance_method(:__temp_bound_method)
8
8
  end
9
-
9
+
10
10
  # Shortcut for <tt>unbind.bind(to)</tt>
11
11
  def bind(to)
12
12
  unbind.bind(to)
13
13
  end
14
14
  end
15
15
  end
16
- end
16
+ end
@@ -5,7 +5,7 @@ require 'stringio'
5
5
  module Packable
6
6
  def self.included(base) #:nodoc:
7
7
  base.class_eval do
8
- class << self
8
+ class << self
9
9
  include PackersClassMethod
10
10
  include ClassMethods
11
11
  end
@@ -26,18 +26,18 @@ module Packable
26
26
  #
27
27
  def packers
28
28
  yield packers if block_given?
29
- Packers.for(self)
29
+ Packers.for(self)
30
30
  end
31
31
  end
32
32
 
33
- module ClassMethods
33
+ module ClassMethods
34
34
 
35
35
  def unpack(s, options = :default)
36
36
  return s.unpack(options).first if options.is_a? String
37
37
  StringIO.new(s).packed.read(self, options)
38
38
  end
39
-
40
- # Default +read_packed+ calls either the instance method <tt>read_packed</tt> or the
39
+
40
+ # Default +read_packed+ calls either the instance method <tt>read_packed</tt> or the
41
41
  # class method +unpack_string+. Choose:
42
42
  # * define a class method +read_packed+ that returns the newly read object
43
43
  # * define an instance method +read_packed+ which reads the io into +self+
@@ -57,5 +57,5 @@ module Packable
57
57
  end
58
58
  end
59
59
 
60
- end
61
- end
60
+ end
61
+ end
@@ -1,9 +1,9 @@
1
1
  module Packable
2
-
2
+
3
3
  # Packers for any packable class.
4
4
  class Packers < Hash
5
5
  SPECIAL = [:default, :merge_all].freeze
6
-
6
+
7
7
  # Usage:
8
8
  # PackableClass.packers.set :shortcut, :option => value, ...
9
9
  # PackableClass.packers { |p| p.set...; p.set... }
@@ -42,7 +42,7 @@ module Packable
42
42
  end
43
43
 
44
44
  @@packers_for_class = Hash.new{|h, klass| h[klass] = Packers.new(klass)}
45
-
45
+
46
46
  # Returns the configuration for the given +klass+.
47
47
  def self.for(klass)
48
48
  @@packers_for_class[klass]
@@ -59,7 +59,7 @@ module Packable
59
59
  end
60
60
  r
61
61
  end
62
-
62
+
63
63
  def self.to_object_option_list(*arg) #:nodoc:
64
64
  r=[]
65
65
  until arg.empty? do
@@ -85,7 +85,6 @@ module Packable
85
85
  raise "Couldn't find packing option #{key}"
86
86
  end
87
87
 
88
-
89
88
  end
90
89
 
91
90
  # Use to capture the blocks given to read/write
@@ -103,5 +102,5 @@ module Packable
103
102
  options[:write_packed] = block.unbind
104
103
  end
105
104
  end
106
-
107
- end
105
+
106
+ end
@@ -1,3 +1,3 @@
1
1
  module Packable
2
- VERSION = "1.3.8"
2
+ VERSION = "1.3.14"
3
3
  end
@@ -6,6 +6,7 @@ require 'packable/version'
6
6
  Gem::Specification.new do |gem|
7
7
  gem.name = "packable"
8
8
  gem.version = Packable::VERSION
9
+ gem.homepage = "https://github.com/marcandre/packable"
9
10
  gem.authors = ["Marc-André Lafortune"]
10
11
  gem.email = ["github@marc-andre.ca"]
11
12
  gem.description = %q{If you need to do read and write binary data, there is of course <Array::pack and String::unpack\n The packable library makes (un)packing nicer, smarter and more powerful.\n}
@@ -16,6 +17,7 @@ Gem::Specification.new do |gem|
16
17
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
18
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
19
  gem.require_paths = ["lib"]
20
+ gem.required_ruby_version = '>= 1.8.7'
19
21
  gem.add_runtime_dependency 'backports'
20
22
  gem.add_development_dependency 'minitest'
21
23
  gem.add_development_dependency 'shoulda'
@@ -2,7 +2,7 @@ require File.expand_path(File.dirname(__FILE__) + '/test_helper')
2
2
  # Warning: ugly...
3
3
  class MyHeader < Struct.new(:signature, :nb_blocks)
4
4
  include Packable
5
-
5
+
6
6
  def write_packed(packedio, options)
7
7
  packedio << [signature, {:bytes=>3}] << [nb_blocks, :short]
8
8
  end
@@ -10,19 +10,17 @@ class MyHeader < Struct.new(:signature, :nb_blocks)
10
10
  def read_packed(packedio, options)
11
11
  self.signature, self.nb_blocks = packedio >> [String, {:bytes => 3}] >> :short
12
12
  end
13
-
13
+
14
14
  def ohoh
15
15
  :ahah
16
16
  end
17
17
  end
18
18
 
19
-
20
- class PackableDocTest < Minitest::Test
19
+ class PackableDocTest < Minitest::Test
21
20
  def test_doc
22
21
 
23
22
  assert_equal [1,2,3], StringIO.new("\000\001\000\002\000\003").each(:short).to_a
24
23
 
25
-
26
24
  String.packers.set :flv_signature, :bytes => 3, :fill => "FLV"
27
25
 
28
26
  assert_equal "xFL", "x".pack(:flv_signature)
@@ -31,12 +29,12 @@ class PackableDocTest < Minitest::Test
31
29
  p.set :merge_all, :fill => "*" # Unless explicitly specified, :fill will now be "*"
32
30
  p.set :default, :bytes => 8 # If no option is given, this will act as default
33
31
  end
34
-
32
+
35
33
  assert_equal "ab******", "ab".pack
36
34
  assert_equal "ab**", "ab".pack(:bytes=>4)
37
35
  assert_equal "ab", "ab".pack(:fill => "!")
38
36
  assert_equal "ab!!", "ab".pack(:fill => "!", :bytes => 4)
39
-
37
+
40
38
  String.packers do |p|
41
39
  p.set :creator, :bytes => 4
42
40
  p.set :app_type, :creator
@@ -44,9 +42,9 @@ class PackableDocTest < Minitest::Test
44
42
  p.set :merge_all, :fill => " "
45
43
  p.set :eigth_bytes, :bytes => 8
46
44
  end
47
-
45
+
48
46
  assert_equal "hello".pack(:app_type), "hell"
49
-
47
+
50
48
  assert_equal [["sig", 1, "hello, w"]]*4,
51
49
  [
52
50
  lambda { |io| io >> :flv_signature >> Integer >> [String, {:bytes => 8}] },
@@ -54,8 +52,7 @@ class PackableDocTest < Minitest::Test
54
52
  lambda { |io| io.read(:flv_signature, Integer, String, {:bytes => 8}) },
55
53
  lambda { |io| [io.read(:flv_signature), io.read(Integer), io.read(String, {:bytes => 8})] }
56
54
  ].map {|proc| proc.call(StringIO.new("sig\000\000\000\001hello, world"))}
57
-
58
-
55
+
59
56
  ex = "xFL\000\000\000BHello "
60
57
  [
61
58
  lambda { |io| io << "x".pack(:flv_signature) << 66.pack << "Hello".pack(:bytes => 8)}, # returns io
@@ -68,31 +65,28 @@ class PackableDocTest < Minitest::Test
68
65
  ios.rewind
69
66
  assert_equal ex, ios.read, "With #{proc}"
70
67
  end
71
-
68
+
72
69
  #insure StringIO class is not affected
73
70
  ios = StringIO.new
74
71
  ios.packed
75
72
  ios << 66
76
73
  ios.rewind
77
74
  assert_equal "66", ios.read
78
-
79
-
75
+
80
76
  String.packers.set :length_encoded do |packer|
81
77
  packer.write { |io| io << length << self }
82
78
  packer.read { |io| io.read(io.read(Integer)) }
83
79
  end
84
-
80
+
85
81
  assert_equal "\000\000\000\006hello!", "hello!".pack(:length_encoded)
86
82
  assert_equal ["this", "is", "great!"], ["this", "is", "great!"].pack(*[:length_encoded]*3).unpack(*[:length_encoded]*3)
87
-
83
+
88
84
  h = MyHeader.new("FLV", 65)
89
85
  assert_equal "FLV\000A", h.pack
90
86
  h2, = StringIO.new("FLV\000A") >> MyHeader
91
87
  assert_equal h, h2
92
88
  assert_equal h.ohoh, h2.ohoh
93
89
 
94
-
95
-
96
90
  Object.packers.set :with_class do |packer|
97
91
  packer.write { |io| io << [self.class.name, :length_encoded] << self }
98
92
  packer.read do |io|
@@ -103,4 +97,4 @@ class PackableDocTest < Minitest::Test
103
97
  ar = [42, MyHeader.new("FLV", 65)]
104
98
  assert_equal ar, ar.pack(:with_class, :with_class).unpack(:with_class, :with_class)
105
99
  end
106
- end
100
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: packable
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.8
4
+ version: 1.3.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marc-André Lafortune
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-22 00:00:00.000000000 Z
11
+ date: 2020-06-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: backports
@@ -107,15 +107,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
- version: '0'
110
+ version: 1.8.7
111
111
  required_rubygems_version: !ruby/object:Gem::Requirement
112
112
  requirements:
113
113
  - - ">="
114
114
  - !ruby/object:Gem::Version
115
115
  version: '0'
116
116
  requirements: []
117
- rubyforge_project:
118
- rubygems_version: 2.2.2
117
+ rubygems_version: 3.1.2
119
118
  signing_key:
120
119
  specification_version: 4
121
120
  summary: Extensive packing and unpacking capabilities
@@ -123,4 +122,3 @@ test_files:
123
122
  - test/packing_doc_test.rb
124
123
  - test/packing_test.rb
125
124
  - test/test_helper.rb
126
- has_rdoc: