collapsium 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 380030070f1838be3f5a7955fcd6e146398653f7
4
- data.tar.gz: 18862980c22abb357b61c26d867a21d397c4faef
3
+ metadata.gz: 39373bf60c53fa0099f0f3066725d0de62448e37
4
+ data.tar.gz: 460a9f149f29cd83210c72e5abd2715046329499
5
5
  SHA512:
6
- metadata.gz: c5be77bf133c4042d193a4f10c4dafbbc2805da3dc4497b29e11802d33a4b34726a2af79642d9f6423f9de14746a46d2a3acc7ff655d1e14d1ba11ca68ba3055
7
- data.tar.gz: 55fa9036b582b1cb8f708c1d384e006b2bf822253ed213eff8204fbeae2e4a159b578ac6a1330ac380ab75b875f637e8cf4385ed8c57760ce0888e3e10d8d29c
6
+ metadata.gz: a1cf946152d25f4eadd5db380fc7907188b0152061b6d0be39e4676442ef272c8fb1efbfce2eba421be5e869466c09fced926dec919592d1cfc3d88228604acf
7
+ data.tar.gz: 39b05aa8b8d64e4608a56f241f7e97ade7a2379eb8867a315cd4480c2360d61cf4c51f90f2b5a67e421be6add9dacef01b96d3ef1c8d8d16c6d2485d4b1e570f
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- collapsium (0.1.0)
4
+ collapsium (0.2.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -0,0 +1,70 @@
1
+ # coding: utf-8
2
+ #
3
+ # collapsium
4
+ # https://github.com/jfinkhaeuser/collapsium
5
+ #
6
+ # Copyright (c) 2016 Jens Finkhaeuser and other collapsium contributors.
7
+ # All rights reserved.
8
+ #
9
+
10
+ module Collapsium
11
+ ##
12
+ # Provides prototype matching for Hashes. See #prototype_match
13
+ module PrototypeMatch
14
+ ##
15
+ # Given a prototype Hash, returns true if (recursively):
16
+ # - this hash contains all the prototype's keys, and
17
+ # - this hash contains all the prototype's values
18
+ # Note that this is not the same as equality. If the prototype provides a
19
+ # nil value for any key, then any value in this Hash is considered to be
20
+ # valid.
21
+ # @param prototype (Hash) The prototype to match against.
22
+ # @param strict (Boolean) If true, this Hash may not contain keys that are
23
+ # not present in the prototype.
24
+ # @return (Boolean) True if matching succeeds, false otherwise.
25
+ def prototype_match(prototype, strict = false)
26
+ # Prototype contains keys not in the Hash,so that's a failure.
27
+ if not (prototype.keys - keys).empty?
28
+ return false
29
+ end
30
+
31
+ # In strict evaluation, the Hash may also not contain keys that are not
32
+ # in the prototoype.
33
+ if strict and not (keys - prototype.keys).empty?
34
+ return false
35
+ end
36
+
37
+ # Now we have to examine the prototype's values.
38
+ prototype.each do |key, value|
39
+ # We can skip any nil values in the prototype. They exist only to ensure
40
+ # the key is present.
41
+ if value.nil?
42
+ next
43
+ end
44
+
45
+ # If the prototype value is a Hash, then the Hash value also has to be,
46
+ # and we have to recurse into this Hash.
47
+ if value.is_a?(Hash)
48
+ if not self[key].is_a?(Hash)
49
+ return false
50
+ end
51
+
52
+ self[key].extend(PrototypeMatch)
53
+ if not self[key].prototype_match(value)
54
+ return false
55
+ end
56
+
57
+ next
58
+ end
59
+
60
+ # Otherwise the prototype value must be equal to the Hash's value
61
+ if self[key] != value
62
+ return false
63
+ end
64
+ end
65
+
66
+ # All other cases must be true.
67
+ return true
68
+ end
69
+ end # module PrototypeMatch
70
+ end # module Collapsium
@@ -0,0 +1,36 @@
1
+ # coding: utf-8
2
+ #
3
+ # collapsium
4
+ # https://github.com/jfinkhaeuser/collapsium
5
+ #
6
+ # Copyright (c) 2016 Jens Finkhaeuser and other collapsium contributors.
7
+ # All rights reserved.
8
+ #
9
+
10
+ module Collapsium
11
+ ##
12
+ # Provides recursive (deep) dup function for hashes.
13
+ module RecursiveDup
14
+ def recursive_dup
15
+ ret = map do |k, v|
16
+ # Hash values, recurse into them.
17
+ if v.is_a?(Hash)
18
+ n = v.dup # we duplicate v to not extend it.
19
+ n.extend(RecursiveDup)
20
+ next [k, n.recursive_dup]
21
+ end
22
+
23
+ begin
24
+ # Other duplicatable values
25
+ next [k, v.dup]
26
+ rescue TypeError
27
+ # Values such as e.g. Fixnum
28
+ next [k, v]
29
+ end
30
+ end
31
+ return Hash[ret]
32
+ end
33
+
34
+ alias deep_dup recursive_dup
35
+ end # module RecursiveDup
36
+ end # module Collapsium
@@ -9,7 +9,7 @@
9
9
 
10
10
  module Collapsium
11
11
  ##
12
- # Provides recursive merge functions for hashes. Used in PathedHash.
12
+ # Provides recursive merge functions for hashes.
13
13
  module RecursiveMerge
14
14
  ##
15
15
  # Recursively merge `:other` into this Hash.
@@ -0,0 +1,80 @@
1
+ # coding: utf-8
2
+ #
3
+ # collapsium
4
+ # https://github.com/jfinkhaeuser/collapsium
5
+ #
6
+ # Copyright (c) 2016 Jens Finkhaeuser and other collapsium contributors.
7
+ # All rights reserved.
8
+ #
9
+
10
+ module Collapsium
11
+ ##
12
+ # Provides recursive sort functions for hashes.
13
+ module RecursiveSort
14
+ ##
15
+ # Recursively sort a Hash by its keys. Without a block, this function will
16
+ # not be able to compare keys of different size.
17
+ def recursive_sort!(&block)
18
+ return keys.sort(&block).reduce(self) do |seed, key|
19
+ # Delete (and later re-insert) value for ordering
20
+ value = self[key]
21
+ delete(key)
22
+
23
+ # Recurse into Hash values
24
+ if value.is_a?(Hash)
25
+ value.extend(RecursiveSort)
26
+ value.recursive_sort!(&block)
27
+ end
28
+
29
+ # re-insert value
30
+ self[key] = value
31
+
32
+ next seed
33
+ end
34
+ end
35
+
36
+ ##
37
+ # Same as #recursive_sort!, but returns a copy.
38
+ def recursive_sort(&block)
39
+ ret = nil
40
+ if respond_to?(:recursive_dup)
41
+ ret = recursive_dup
42
+ else
43
+ ret = dup
44
+ end
45
+ ret.extend(RecursiveSort)
46
+ return ret.recursive_sort!(&block)
47
+ end
48
+
49
+ # def recursive_merge!(other, overwrite = true)
50
+ # if other.nil?
51
+ # return self
52
+ # end
53
+ #
54
+ # merger = proc do |_, v1, v2|
55
+ # # rubocop:disable Style/GuardClause
56
+ # if v1.is_a? Hash and v2.is_a? Hash
57
+ # next v1.merge(v2, &merger)
58
+ # elsif v1.is_a? Array and v2.is_a? Array
59
+ # next v1 + v2
60
+ # end
61
+ # if overwrite
62
+ # next v2
63
+ # else
64
+ # next v1
65
+ # end
66
+ # # rubocop:enable Style/GuardClause
67
+ # end
68
+ # merge!(other, &merger)
69
+ # end
70
+ #
71
+ # ##
72
+ # # Same as `dup.recursive_merge!`
73
+ # # @param (see #recursive_merge!)
74
+ # def recursive_merge(other, overwrite = true)
75
+ # copy = dup
76
+ # copy.extend(RecursiveMerge)
77
+ # return copy.recursive_merge!(other, overwrite)
78
+ # end
79
+ end # module RecursiveSort
80
+ end # module Collapsium
@@ -8,15 +8,21 @@
8
8
  #
9
9
 
10
10
  require 'collapsium/recursive_merge'
11
+ require 'collapsium/recursive_dup'
12
+ require 'collapsium/recursive_sort'
11
13
  require 'collapsium/indifferent_access'
12
14
  require 'collapsium/pathed_access'
15
+ require 'collapsium/prototype_match'
13
16
 
14
17
  module Collapsium
15
18
 
16
19
  # A Hash that includes all the different Hash extensions in collapsium
17
20
  class UberHash < Hash
18
21
  include RecursiveMerge
22
+ include RecursiveDup
23
+ include RecursiveSort
19
24
  include PathedAccess
25
+ include PrototypeMatch
20
26
 
21
27
  def initialize(*args)
22
28
  super
@@ -8,5 +8,5 @@
8
8
  #
9
9
  module Collapsium
10
10
  # The current release version
11
- VERSION = "0.1.0".freeze
11
+ VERSION = "0.2.0".freeze
12
12
  end
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+ require_relative '../lib/collapsium/prototype_match'
3
+
4
+ describe ::Collapsium::PrototypeMatch do
5
+ before :each do
6
+ @hash = {
7
+ 'a' => 1,
8
+ :c => {
9
+ 'd' => 4,
10
+ 'f' => 6,
11
+ 42 => 5,
12
+ },
13
+ 'b' => 2,
14
+ }
15
+ @hash.extend(::Collapsium::PrototypeMatch)
16
+ end
17
+
18
+ it "matches a prototype containing any individual key (non-strict)" do
19
+ # Keys exist in hash
20
+ expect(@hash.prototype_match('a' => nil)).to be_truthy
21
+ expect(@hash.prototype_match('b' => nil)).to be_truthy
22
+ expect(@hash.prototype_match(c: nil)).to be_truthy
23
+
24
+ # Key doesn't exist in hash
25
+ expect(@hash.prototype_match(foo: nil)).to be_falsy
26
+ end
27
+
28
+ it "does't match a prototype containing an individual key in strict mode" do
29
+ expect(@hash.prototype_match({ 'a' => nil }, true)).to be_falsy
30
+ end
31
+
32
+ it "matches nested prototypes (non-strict)" do
33
+ proto = {
34
+ c: {
35
+ 'd' => nil,
36
+ }
37
+ }
38
+ expect(@hash.prototype_match(proto)).to be_truthy
39
+ end
40
+
41
+ it "doesn't match nested prototypes (strict)" do
42
+ proto = {
43
+ c: {
44
+ 'd' => nil,
45
+ }
46
+ }
47
+ expect(@hash.prototype_match(proto, true)).to be_falsy
48
+ end
49
+
50
+ it "fails if a value type mismatches a prototype value's type" do
51
+ proto = {
52
+ c: {
53
+ 'd' => {},
54
+ }
55
+ }
56
+ expect(@hash.prototype_match(proto)).to be_falsy
57
+ end
58
+
59
+ it "fails if a value mismatches a prototype value" do
60
+ proto = {
61
+ c: {
62
+ 'd' => 42,
63
+ }
64
+ }
65
+ expect(@hash.prototype_match(proto)).to be_falsy
66
+ end
67
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+ require_relative '../lib/collapsium/recursive_dup'
3
+
4
+ describe ::Collapsium::RecursiveDup do
5
+ it "duplicates nested values" do
6
+ h = {
7
+ 'a' => 1,
8
+ :c => {
9
+ 'd' => 4,
10
+ 'f' => 6,
11
+ 42 => 5,
12
+ },
13
+ 'b' => 2,
14
+ }
15
+ h.extend(::Collapsium::RecursiveDup)
16
+
17
+ h2 = h.deep_dup
18
+
19
+ expect(h2.object_id).not_to eql h.object_id
20
+ expect(h2[:c].object_id).not_to eql h[:c].object_id
21
+ end
22
+ end
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+ require_relative '../lib/collapsium/recursive_sort'
3
+
4
+ describe ::Collapsium::RecursiveSort do
5
+ before :each do
6
+ @tester = {}
7
+ @tester.extend(::Collapsium::RecursiveSort)
8
+ end
9
+
10
+ it "sorts a nested hash with string keys in place" do
11
+ h = {
12
+ 'a' => 1,
13
+ 'c' => {
14
+ 'd' => 4,
15
+ 'f' => 6,
16
+ 'e' => 5,
17
+ },
18
+ 'b' => 2,
19
+ }
20
+ h.extend(::Collapsium::RecursiveSort)
21
+
22
+ h.recursive_sort!
23
+
24
+ expect(h.keys).to eql %w(a b c)
25
+ expect(h['c'].keys).to eql %w(d e f)
26
+ end
27
+
28
+ it "duplicates and sorts an outer hash (not deep)" do
29
+ h = {
30
+ 'a' => 1,
31
+ 'c' => {
32
+ 'd' => 4,
33
+ 'f' => 6,
34
+ 'e' => 5,
35
+ },
36
+ 'b' => 2,
37
+ }
38
+ h.extend(::Collapsium::RecursiveSort)
39
+
40
+ h2 = h.recursive_sort
41
+
42
+ # Only the new outer hash's keys are sorted
43
+ expect(h.keys).to eql %w(a c b)
44
+ expect(h2.keys).to eql %w(a b c)
45
+
46
+ # Both inner hashes are sorted because dup isn't deep
47
+ expect(h['c'].keys).to eql %w(d e f)
48
+ expect(h2['c'].keys).to eql %w(d e f)
49
+
50
+ # Similar with object IDs
51
+ expect(h.object_id).not_to eql h2.object_id
52
+ expect(h['c'].object_id).to eql h2['c'].object_id
53
+ end
54
+
55
+ it "it uses RecursiveDup if present" do
56
+ require_relative '../lib/collapsium/recursive_dup'
57
+ h = {
58
+ 'a' => 1,
59
+ 'c' => {
60
+ 'd' => 4,
61
+ 'f' => 6,
62
+ 'e' => 5,
63
+ },
64
+ 'b' => 2,
65
+ }
66
+ h.extend(::Collapsium::RecursiveSort)
67
+ h.extend(::Collapsium::RecursiveDup)
68
+
69
+ h2 = h.recursive_sort
70
+
71
+ # Only the new outer hash's keys are sorted
72
+ expect(h.keys).to eql %w(a c b)
73
+ expect(h2.keys).to eql %w(a b c)
74
+
75
+ # Only the new inner hash's keys are sorted
76
+ expect(h['c'].keys).to eql %w(d f e)
77
+ expect(h2['c'].keys).to eql %w(d e f)
78
+
79
+ # Similar with object IDs
80
+ expect(h.object_id).not_to eql h2.object_id
81
+ expect(h['c'].object_id).not_to eql h2['c'].object_id
82
+ end
83
+ end
data/spec/spec_helper.rb CHANGED
@@ -6,4 +6,6 @@ end
6
6
 
7
7
  # Always start SimpleCov
8
8
  require 'simplecov'
9
- SimpleCov.start
9
+ SimpleCov.start do
10
+ add_filter 'spec'
11
+ end
@@ -41,4 +41,21 @@ describe Collapsium::UberHash do
41
41
  x = ::Collapsium::UberHash.new
42
42
  expect(x.empty?).to be_truthy
43
43
  end
44
+
45
+ it "has recursive_dup support" do
46
+ x = ::Collapsium::UberHash.new
47
+ expect(x.respond_to?(:recursive_dup)).to be_truthy
48
+ expect(x.respond_to?(:deep_dup)).to be_truthy
49
+ end
50
+
51
+ it "has recursive_sort support" do
52
+ x = ::Collapsium::UberHash.new
53
+ expect(x.respond_to?(:recursive_sort)).to be_truthy
54
+ expect(x.respond_to?(:recursive_sort!)).to be_truthy
55
+ end
56
+
57
+ it "has prototype_match support" do
58
+ x = ::Collapsium::UberHash.new
59
+ expect(x.respond_to?(:prototype_match)).to be_truthy
60
+ end
44
61
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: collapsium
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jens Finkhaeuser
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-11 00:00:00.000000000 Z
11
+ date: 2016-05-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -116,12 +116,18 @@ files:
116
116
  - lib/collapsium.rb
117
117
  - lib/collapsium/indifferent_access.rb
118
118
  - lib/collapsium/pathed_access.rb
119
+ - lib/collapsium/prototype_match.rb
120
+ - lib/collapsium/recursive_dup.rb
119
121
  - lib/collapsium/recursive_merge.rb
122
+ - lib/collapsium/recursive_sort.rb
120
123
  - lib/collapsium/uber_hash.rb
121
124
  - lib/collapsium/version.rb
122
125
  - spec/indifferent_access_spec.rb
123
126
  - spec/pathed_access_spec.rb
127
+ - spec/prototype_match_spec.rb
128
+ - spec/recursive_dup_spec.rb
124
129
  - spec/recursive_merge_spec.rb
130
+ - spec/recursive_sort_spec.rb
125
131
  - spec/spec_helper.rb
126
132
  - spec/uber_hash_spec.rb
127
133
  homepage: https://github.com/jfinkhaeuser/collapsium
@@ -151,7 +157,10 @@ summary: Provides various Hash extensions, and an UberHash class that uses them
151
157
  test_files:
152
158
  - spec/indifferent_access_spec.rb
153
159
  - spec/pathed_access_spec.rb
160
+ - spec/prototype_match_spec.rb
161
+ - spec/recursive_dup_spec.rb
154
162
  - spec/recursive_merge_spec.rb
163
+ - spec/recursive_sort_spec.rb
155
164
  - spec/spec_helper.rb
156
165
  - spec/uber_hash_spec.rb
157
166
  has_rdoc: