ostruct 0.1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d125c51b4a6541c0dcb5422065b685c156e847218380e2c01f1ef8fac08e40dc
4
+ data.tar.gz: 7c5aa451998687071f22794e2e24ea644e7a6698e4eebe608ccd42a6cdf3199c
5
+ SHA512:
6
+ metadata.gz: c58234c3f25e5eee4f47faf91c0016051e9bd72016d38a54248b1695424016d4cb46be9a09ef29837cd268cac57f0c7eebe1e5c330d218c580b304f1210764bc
7
+ data.tar.gz: 3698d2ab77b8c9904b43143795226e9f3abce36a55fc2923fc7ed65f4cf48d60790ec55e2f43d6bfb75c0f010aa23b32c08d73c00f6468420f4fc8131dce22dc
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ Gemfile.lock
@@ -0,0 +1,6 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.5.1
5
+ - ruby-head
6
+ before_install: gem install bundler -v 1.15.4
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in ostruct.gemspec
6
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved.
2
+
3
+ Redistribution and use in source and binary forms, with or without
4
+ modification, are permitted provided that the following conditions
5
+ are met:
6
+ 1. Redistributions of source code must retain the above copyright
7
+ notice, this list of conditions and the following disclaimer.
8
+ 2. Redistributions in binary form must reproduce the above copyright
9
+ notice, this list of conditions and the following disclaimer in the
10
+ documentation and/or other materials provided with the distribution.
11
+
12
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
13
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
16
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22
+ SUCH DAMAGE.
@@ -0,0 +1,69 @@
1
+ # OpenStruct
2
+
3
+ An OpenStruct is a data structure, similar to a Hash, that allows the definition of arbitrary attributes with their ccompanying values. This is accomplished by using Ruby's metaprogramming to define methods on the class itself.
4
+
5
+ ## Installation
6
+
7
+ The `ostruct` library comes pre-packaged with Ruby. No installation is necessary.
8
+
9
+ ## Usage
10
+
11
+ ```
12
+ require "ostruct"
13
+
14
+ person = OpenStruct.new
15
+ person.name = "John Smith"
16
+ person.age = 70
17
+
18
+ person.name # => "John Smith"
19
+ person.age # => 70
20
+ person.address # => nil
21
+ ```
22
+
23
+ An OpenStruct employs a Hash internally to store the attributes and values and can even be initialized with one:
24
+
25
+ ```
26
+ australia = OpenStruct.new(:country => "Australia", :capital => "Canberra")
27
+ # => #<OpenStruct country="Australia", capital="Canberra">
28
+ ```
29
+
30
+ Hash keys with spaces or characters that could normally not be used for method calls (e.g. <code>()[]*</code>) will not be immediately available on the OpenStruct object as a method for retrieval or assignment, but can still be reached through the Object#send method.
31
+
32
+ ```
33
+ measurements = OpenStruct.new("length (in inches)" => 24)
34
+ measurements.send("length (in inches)") # => 24
35
+
36
+ message = OpenStruct.new(:queued? => true)
37
+ message.queued? # => true
38
+ message.send("queued?=", false)
39
+ message.queued? # => false
40
+ ```
41
+
42
+ Removing the presence of an attribute requires the execution of the delete_field method as setting the property value to +nil+ will not remove the attribute.
43
+
44
+ ```
45
+ first_pet = OpenStruct.new(:name => "Rowdy", :owner => "John Smith")
46
+ second_pet = OpenStruct.new(:name => "Rowdy")
47
+
48
+ first_pet.owner = nil
49
+ first_pet # => #<OpenStruct name="Rowdy", owner=nil>
50
+ first_pet == second_pet # => false
51
+
52
+ first_pet.delete_field(:owner)
53
+ first_pet # => #<OpenStruct name="Rowdy">
54
+ first_pet == second_pet # => true
55
+ ```
56
+
57
+ ## Development
58
+
59
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
60
+
61
+ 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`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
62
+
63
+ ## Contributing
64
+
65
+ Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/ostruct.
66
+
67
+ ## License
68
+
69
+ The gem is available as open source under the terms of the [2-Clause BSD License](https://opensource.org/licenses/BSD-2-Clause).
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test" << "test/lib"
6
+ t.libs << "lib"
7
+ t.test_files = FileList['test/**/test_*.rb']
8
+ end
9
+
10
+ task :default => [:test]
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "ostruct"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,369 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # = ostruct.rb: OpenStruct implementation
4
+ #
5
+ # Author:: Yukihiro Matsumoto
6
+ # Documentation:: Gavin Sinclair
7
+ #
8
+ # OpenStruct allows the creation of data objects with arbitrary attributes.
9
+ # See OpenStruct for an example.
10
+ #
11
+
12
+ #
13
+ # An OpenStruct is a data structure, similar to a Hash, that allows the
14
+ # definition of arbitrary attributes with their accompanying values. This is
15
+ # accomplished by using Ruby's metaprogramming to define methods on the class
16
+ # itself.
17
+ #
18
+ # == Examples
19
+ #
20
+ # require "ostruct"
21
+ #
22
+ # person = OpenStruct.new
23
+ # person.name = "John Smith"
24
+ # person.age = 70
25
+ #
26
+ # person.name # => "John Smith"
27
+ # person.age # => 70
28
+ # person.address # => nil
29
+ #
30
+ # An OpenStruct employs a Hash internally to store the attributes and values
31
+ # and can even be initialized with one:
32
+ #
33
+ # australia = OpenStruct.new(:country => "Australia", :capital => "Canberra")
34
+ # # => #<OpenStruct country="Australia", capital="Canberra">
35
+ #
36
+ # Hash keys with spaces or characters that could normally not be used for
37
+ # method calls (e.g. <code>()[]*</code>) will not be immediately available
38
+ # on the OpenStruct object as a method for retrieval or assignment, but can
39
+ # still be reached through the Object#send method.
40
+ #
41
+ # measurements = OpenStruct.new("length (in inches)" => 24)
42
+ # measurements.send("length (in inches)") # => 24
43
+ #
44
+ # message = OpenStruct.new(:queued? => true)
45
+ # message.queued? # => true
46
+ # message.send("queued?=", false)
47
+ # message.queued? # => false
48
+ #
49
+ # Removing the presence of an attribute requires the execution of the
50
+ # delete_field method as setting the property value to +nil+ will not
51
+ # remove the attribute.
52
+ #
53
+ # first_pet = OpenStruct.new(:name => "Rowdy", :owner => "John Smith")
54
+ # second_pet = OpenStruct.new(:name => "Rowdy")
55
+ #
56
+ # first_pet.owner = nil
57
+ # first_pet # => #<OpenStruct name="Rowdy", owner=nil>
58
+ # first_pet == second_pet # => false
59
+ #
60
+ # first_pet.delete_field(:owner)
61
+ # first_pet # => #<OpenStruct name="Rowdy">
62
+ # first_pet == second_pet # => true
63
+ #
64
+ #
65
+ # == Implementation
66
+ #
67
+ # An OpenStruct utilizes Ruby's method lookup structure to find and define the
68
+ # necessary methods for properties. This is accomplished through the methods
69
+ # method_missing and define_singleton_method.
70
+ #
71
+ # This should be a consideration if there is a concern about the performance of
72
+ # the objects that are created, as there is much more overhead in the setting
73
+ # of these properties compared to using a Hash or a Struct.
74
+ #
75
+ class OpenStruct
76
+
77
+ #
78
+ # Creates a new OpenStruct object. By default, the resulting OpenStruct
79
+ # object will have no attributes.
80
+ #
81
+ # The optional +hash+, if given, will generate attributes and values
82
+ # (can be a Hash, an OpenStruct or a Struct).
83
+ # For example:
84
+ #
85
+ # require "ostruct"
86
+ # hash = { "country" => "Australia", :capital => "Canberra" }
87
+ # data = OpenStruct.new(hash)
88
+ #
89
+ # data # => #<OpenStruct country="Australia", capital="Canberra">
90
+ #
91
+ def initialize(hash=nil)
92
+ @table = {}
93
+ if hash
94
+ hash.each_pair do |k, v|
95
+ k = k.to_sym
96
+ @table[k] = v
97
+ end
98
+ end
99
+ end
100
+
101
+ # Duplicates an OpenStruct object's Hash table.
102
+ def initialize_copy(orig) # :nodoc:
103
+ super
104
+ @table = @table.dup
105
+ end
106
+
107
+ #
108
+ # Converts the OpenStruct to a hash with keys representing
109
+ # each attribute (as symbols) and their corresponding values.
110
+ #
111
+ # require "ostruct"
112
+ # data = OpenStruct.new("country" => "Australia", :capital => "Canberra")
113
+ # data.to_h # => {:country => "Australia", :capital => "Canberra" }
114
+ #
115
+ def to_h
116
+ @table.dup
117
+ end
118
+
119
+ #
120
+ # :call-seq:
121
+ # ostruct.each_pair {|name, value| block } -> ostruct
122
+ # ostruct.each_pair -> Enumerator
123
+ #
124
+ # Yields all attributes (as symbols) along with the corresponding values
125
+ # or returns an enumerator if no block is given.
126
+ #
127
+ # require "ostruct"
128
+ # data = OpenStruct.new("country" => "Australia", :capital => "Canberra")
129
+ # data.each_pair.to_a # => [[:country, "Australia"], [:capital, "Canberra"]]
130
+ #
131
+ def each_pair
132
+ return to_enum(__method__) { @table.size } unless block_given?
133
+ @table.each_pair{|p| yield p}
134
+ self
135
+ end
136
+
137
+ #
138
+ # Provides marshalling support for use by the Marshal library.
139
+ #
140
+ def marshal_dump
141
+ @table
142
+ end
143
+
144
+ #
145
+ # Provides marshalling support for use by the Marshal library.
146
+ #
147
+ def marshal_load(x)
148
+ @table = x
149
+ end
150
+
151
+ #
152
+ # Used internally to check if the OpenStruct is able to be
153
+ # modified before granting access to the internal Hash table to be modified.
154
+ #
155
+ def modifiable? # :nodoc:
156
+ begin
157
+ @modifiable = true
158
+ rescue
159
+ exception_class = defined?(FrozenError) ? FrozenError : RuntimeError
160
+ raise exception_class, "can't modify frozen #{self.class}", caller(3)
161
+ end
162
+ @table
163
+ end
164
+ private :modifiable?
165
+
166
+ # ::Kernel.warn("do not use OpenStruct#modifiable", uplevel: 1)
167
+ alias modifiable modifiable? # :nodoc:
168
+ protected :modifiable
169
+
170
+ #
171
+ # Used internally to defined properties on the
172
+ # OpenStruct. It does this by using the metaprogramming function
173
+ # define_singleton_method for both the getter method and the setter method.
174
+ #
175
+ def new_ostruct_member!(name) # :nodoc:
176
+ name = name.to_sym
177
+ unless singleton_class.method_defined?(name)
178
+ define_singleton_method(name) { @table[name] }
179
+ define_singleton_method("#{name}=") {|x| modifiable?[name] = x}
180
+ end
181
+ name
182
+ end
183
+ private :new_ostruct_member!
184
+
185
+ # ::Kernel.warn("do not use OpenStruct#new_ostruct_member", uplevel: 1)
186
+ alias new_ostruct_member new_ostruct_member! # :nodoc:
187
+ protected :new_ostruct_member
188
+
189
+ def freeze
190
+ @table.each_key {|key| new_ostruct_member!(key)}
191
+ super
192
+ end
193
+
194
+ def respond_to_missing?(mid, include_private = false) # :nodoc:
195
+ mname = mid.to_s.chomp("=").to_sym
196
+ @table&.key?(mname) || super
197
+ end
198
+
199
+ def method_missing(mid, *args) # :nodoc:
200
+ len = args.length
201
+ if mname = mid[/.*(?==\z)/m]
202
+ if len != 1
203
+ raise ArgumentError, "wrong number of arguments (#{len} for 1)", caller(1)
204
+ end
205
+ modifiable?[new_ostruct_member!(mname)] = args[0]
206
+ elsif len == 0 # and /\A[a-z_]\w*\z/ =~ mid #
207
+ if @table.key?(mid)
208
+ new_ostruct_member!(mid) unless frozen?
209
+ @table[mid]
210
+ end
211
+ else
212
+ begin
213
+ super
214
+ rescue NoMethodError => err
215
+ err.backtrace.shift
216
+ raise
217
+ end
218
+ end
219
+ end
220
+
221
+ #
222
+ # :call-seq:
223
+ # ostruct[name] -> object
224
+ #
225
+ # Returns the value of an attribute.
226
+ #
227
+ # require "ostruct"
228
+ # person = OpenStruct.new("name" => "John Smith", "age" => 70)
229
+ # person[:age] # => 70, same as person.age
230
+ #
231
+ def [](name)
232
+ @table[name.to_sym]
233
+ end
234
+
235
+ #
236
+ # :call-seq:
237
+ # ostruct[name] = obj -> obj
238
+ #
239
+ # Sets the value of an attribute.
240
+ #
241
+ # require "ostruct"
242
+ # person = OpenStruct.new("name" => "John Smith", "age" => 70)
243
+ # person[:age] = 42 # equivalent to person.age = 42
244
+ # person.age # => 42
245
+ #
246
+ def []=(name, value)
247
+ modifiable?[new_ostruct_member!(name)] = value
248
+ end
249
+
250
+ #
251
+ # :call-seq:
252
+ # ostruct.dig(name, ...) -> object
253
+ #
254
+ # Extracts the nested value specified by the sequence of +name+
255
+ # objects by calling +dig+ at each step, returning +nil+ if any
256
+ # intermediate step is +nil+.
257
+ #
258
+ # require "ostruct"
259
+ # address = OpenStruct.new("city" => "Anytown NC", "zip" => 12345)
260
+ # person = OpenStruct.new("name" => "John Smith", "address" => address)
261
+ #
262
+ # person.dig(:address, "zip") # => 12345
263
+ # person.dig(:business_address, "zip") # => nil
264
+ #
265
+ # data = OpenStruct.new(:array => [1, [2, 3]])
266
+ #
267
+ # data.dig(:array, 1, 0) # => 2
268
+ # data.dig(:array, 0, 0) # TypeError: Integer does not have #dig method
269
+ #
270
+ def dig(name, *names)
271
+ begin
272
+ name = name.to_sym
273
+ rescue NoMethodError
274
+ raise TypeError, "#{name} is not a symbol nor a string"
275
+ end
276
+ @table.dig(name, *names)
277
+ end
278
+
279
+ #
280
+ # Removes the named field from the object. Returns the value that the field
281
+ # contained if it was defined.
282
+ #
283
+ # require "ostruct"
284
+ #
285
+ # person = OpenStruct.new(name: "John", age: 70, pension: 300)
286
+ #
287
+ # person.delete_field("age") # => 70
288
+ # person # => #<OpenStruct name="John", pension=300>
289
+ #
290
+ # Setting the value to +nil+ will not remove the attribute:
291
+ #
292
+ # person.pension = nil
293
+ # person # => #<OpenStruct name="John", pension=nil>
294
+ #
295
+ def delete_field(name)
296
+ sym = name.to_sym
297
+ begin
298
+ singleton_class.remove_method(sym, "#{sym}=")
299
+ rescue NameError
300
+ end
301
+ @table.delete(sym) do
302
+ raise NameError.new("no field `#{sym}' in #{self}", sym)
303
+ end
304
+ end
305
+
306
+ InspectKey = :__inspect_key__ # :nodoc:
307
+
308
+ #
309
+ # Returns a string containing a detailed summary of the keys and values.
310
+ #
311
+ def inspect
312
+ ids = (Thread.current[InspectKey] ||= [])
313
+ if ids.include?(object_id)
314
+ detail = ' ...'
315
+ else
316
+ ids << object_id
317
+ begin
318
+ detail = @table.map do |key, value|
319
+ " #{key}=#{value.inspect}"
320
+ end.join(',')
321
+ ensure
322
+ ids.pop
323
+ end
324
+ end
325
+ ['#<', self.class, detail, '>'].join
326
+ end
327
+ alias :to_s :inspect
328
+
329
+ attr_reader :table # :nodoc:
330
+ protected :table
331
+ alias table! table
332
+
333
+ #
334
+ # Compares this object and +other+ for equality. An OpenStruct is equal to
335
+ # +other+ when +other+ is an OpenStruct and the two objects' Hash tables are
336
+ # equal.
337
+ #
338
+ # require "ostruct"
339
+ # first_pet = OpenStruct.new("name" => "Rowdy")
340
+ # second_pet = OpenStruct.new(:name => "Rowdy")
341
+ # third_pet = OpenStruct.new("name" => "Rowdy", :age => nil)
342
+ #
343
+ # first_pet == second_pet # => true
344
+ # first_pet == third_pet # => false
345
+ #
346
+ def ==(other)
347
+ return false unless other.kind_of?(OpenStruct)
348
+ @table == other.table!
349
+ end
350
+
351
+ #
352
+ # Compares this object and +other+ for equality. An OpenStruct is eql? to
353
+ # +other+ when +other+ is an OpenStruct and the two objects' Hash tables are
354
+ # eql?.
355
+ #
356
+ def eql?(other)
357
+ return false unless other.kind_of?(OpenStruct)
358
+ @table.eql?(other.table!)
359
+ end
360
+
361
+ # Computes a hash code for this OpenStruct.
362
+ # Two OpenStruct objects with the same content will have the same hash code
363
+ # (and will compare using #eql?).
364
+ #
365
+ # See also Object#hash.
366
+ def hash
367
+ @table.hash
368
+ end
369
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "ostruct"
5
+ spec.version = "0.1.0"
6
+ spec.authors = ["Marc-Andre Lafortune"]
7
+ spec.email = ["ruby-core@marc-andre.ca"]
8
+
9
+ spec.summary = %q{Class to build custom data structures, similar to a Hash.}
10
+ spec.description = %q{Class to build custom data structures, similar to a Hash.}
11
+ spec.homepage = "https://github.com/ruby/ostruct"
12
+ spec.license = "BSD-2-Clause"
13
+
14
+ spec.files = [".gitignore", ".travis.yml", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "lib/ostruct.rb", "ostruct.gemspec"]
15
+ spec.bindir = "exe"
16
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.add_development_dependency "bundler"
20
+ spec.add_development_dependency "rake"
21
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ostruct
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Marc-Andre Lafortune
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-12-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Class to build custom data structures, similar to a Hash.
42
+ email:
43
+ - ruby-core@marc-andre.ca
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - ".travis.yml"
50
+ - Gemfile
51
+ - LICENSE.txt
52
+ - README.md
53
+ - Rakefile
54
+ - bin/console
55
+ - bin/setup
56
+ - lib/ostruct.rb
57
+ - ostruct.gemspec
58
+ homepage: https://github.com/ruby/ostruct
59
+ licenses:
60
+ - BSD-2-Clause
61
+ metadata: {}
62
+ post_install_message:
63
+ rdoc_options: []
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ requirements: []
77
+ rubyforge_project:
78
+ rubygems_version: 2.7.6
79
+ signing_key:
80
+ specification_version: 4
81
+ summary: Class to build custom data structures, similar to a Hash.
82
+ test_files: []