pure-struct 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (7) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +5 -0
  3. data/LICENSE.txt +20 -0
  4. data/README.md +80 -0
  5. data/VERSION +1 -0
  6. data/lib/pure-struct.rb +142 -0
  7. metadata +149 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: eace9d9756ad91444d1bf732bd2ac036e4b728a7b5fa1814f69a74cc416ae187
4
+ data.tar.gz: 066df3b27a861b53aa452c43ddd7197c7472003b46399b7a6d74efe21365035a
5
+ SHA512:
6
+ metadata.gz: ef02fadf4e5e2689a6a8821fc9decc207193ddd8173036b582c37d3e6a9d30a636ec0d1694bc7bae4d6b6887534df1939b571ce9e1e244d02fb4cb615712a8b6
7
+ data.tar.gz: 43ade6064f84f4904023e571e9559762b04fa101ccad842c47e58af964cf363430d27eb1b37a509a4f719f6ed705100e4b8720eadb6d5d8f9f4dfcf5a464eab7
@@ -0,0 +1,5 @@
1
+ # Change Log
2
+
3
+ ## 1.0.0
4
+
5
+ - Pure Ruby re-implementation of Struct
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2021 Andy maleh
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,80 @@
1
+ # Pure Struct
2
+ [![Gem Version](https://badge.fury.io/rb/pure-struct.svg)](http://badge.fury.io/rb/pure-struct)
3
+ [![rspec](https://github.com/AndyObtiva/pure-struct/workflows/rspec/badge.svg)](https://github.com/AndyObtiva/pure-struct/actions?query=workflow%3Arspec)
4
+ [![Coverage Status](https://coveralls.io/repos/github/AndyObtiva/pure-struct/badge.svg?branch=master)](https://coveralls.io/github/AndyObtiva/pure-struct?branch=master)
5
+ [![Maintainability](https://api.codeclimate.com/v1/badges/2659b419fd5f7d38e443/maintainability)](https://codeclimate.com/github/AndyObtiva/pure-struct/maintainability)
6
+
7
+ Pure [Ruby](https://www.ruby-lang.org/) re-implementation of [Struct](https://ruby-doc.org/core-2.7.0/Struct.html) to ensure cross-Ruby functionality where needed (e.g. [Opal](https://opalrb.com/))
8
+
9
+ It is useful when:
10
+ - There is a need for a Struct class that works consistently across esoteric implementations of [Ruby](https://www.ruby-lang.org/) like [Opal](https://opalrb.com/). This is useful when writing cross-[Ruby](https://www.ruby-lang.org/) apps like those of [Glimmer](https://github.com/AndyObtiva/glimmer) relying on [YASL](https://github.com/AndyObtiva/yasl) (Yet Another Serialization Library) in [Opal](https://opalrb.com/).
11
+ - There is a need to meta-program Struct's data
12
+ - There are no big performance requirements that demand native [Struct](https://ruby-doc.org/core-2.7.0/Struct.html)
13
+
14
+ In all other cases, stick to native [Ruby Struct](https://ruby-doc.org/core-2.7.0/Struct.html) instead since it's optimized for performance.
15
+
16
+ ## Usage Instructions
17
+
18
+ Run:
19
+
20
+ `gem install pure-struct`
21
+
22
+ Or add to [Gemfile](https://bundler.io/man/gemfile.5.html):
23
+
24
+ ```ruby
25
+ gem 'pure-struct', '~> 1.0.0'
26
+ ```
27
+
28
+ And, run:
29
+
30
+ `bundle`
31
+
32
+ Finally, require in [Ruby](https://www.ruby-lang.org/) code:
33
+
34
+ ```ruby
35
+ require 'pure-struct'
36
+ ```
37
+
38
+ Note that it removes the native `Struct` implementation first, aliasing as `NativeStruct` should you still need it, and then redefining `Struct` in pure [Ruby](https://www.ruby-lang.org/).
39
+
40
+ Optionally, you may code block the require statement by a specific [Ruby](https://www.ruby-lang.org/) engine like [Opal](https://opalrb.com/):
41
+
42
+ ```
43
+ if RUBY_ENGINE == 'opal'
44
+ require 'pure-struct'
45
+ end
46
+ ```
47
+
48
+ ## Contributing to pure-struct
49
+
50
+ - Check out the latest master to make sure the feature hasn't been
51
+ implemented or the bug hasn't been fixed yet.
52
+ - Check out the issue tracker to make sure someone already hasn't
53
+ requested it and/or contributed it.
54
+ - Fork the project.
55
+ - Start a feature/bugfix branch.
56
+ - Commit and push until you are happy with your contribution.
57
+ - Make sure to add tests for it. This is important so I don't break it
58
+ in a future version unintentionally.
59
+ - Please try not to mess with the Rakefile, version, or history. If
60
+ you want to have your own version, or is otherwise necessary, that
61
+ is fine, but please isolate to its own commit so I can cherry-pick
62
+ around it.
63
+
64
+ ## Software Process
65
+
66
+ [Glimmer Process](https://github.com/AndyObtiva/glimmer/blob/master/PROCESS.md)
67
+
68
+ ## TODO
69
+
70
+ [TODO.md](TODO.md)
71
+
72
+ ## Change Log
73
+
74
+ [CHANGELOG.md](CHANGELOG.md)
75
+
76
+ ## Copyright
77
+
78
+ [MIT](LICENSE.txt)
79
+
80
+ Copyright (c) 2021 Andy Maleh.
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
@@ -0,0 +1,142 @@
1
+ # Copyright (c) 2021 Andy maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ NativeStruct = Struct
23
+ Object.send(:remove_const, :Struct) if Object.constants.include?(:Struct)
24
+
25
+ # Optional re-implmentation of Struct in Pure Ruby (to get around JS issues in Opal Struct)
26
+ class Struct
27
+ class << self
28
+ CLASS_DEFINITION_FOR_ATTRIBUTES = lambda do |attributes, keyword_init|
29
+ lambda do |defined_class|
30
+ attributes.each do |attribute|
31
+ define_method(attribute) do
32
+ self[attribute]
33
+ end
34
+ define_method("#{attribute}=") do |value|
35
+ self[attribute] = value
36
+ end
37
+ end
38
+
39
+ define_method(:members) do
40
+ (@members ||= attributes).clone
41
+ end
42
+
43
+ def []=(attribute, value)
44
+ normalized_attribute = attribute.to_sym
45
+ raise NameError, "no member #{attribute} in struct" unless @members.include?(normalized_attribute)
46
+ @member_values[normalized_attribute] = value
47
+ end
48
+
49
+ def [](attribute)
50
+ normalized_attribute = attribute.to_sym
51
+ raise NameError, "no member #{attribute} in struct" unless @members.include?(normalized_attribute)
52
+ @member_values[normalized_attribute]
53
+ end
54
+
55
+ def each(&block)
56
+ to_a.each(&block)
57
+ end
58
+
59
+ def each_pair(&block)
60
+ @member_values.each_pair(&block)
61
+ end
62
+
63
+ def to_h
64
+ @member_values.clone
65
+ end
66
+
67
+ def to_a
68
+ @member_values.values
69
+ end
70
+
71
+ def size
72
+ @members.size
73
+ end
74
+ alias length size
75
+
76
+ def dig(*args)
77
+ @member_values.dig(*args)
78
+ end
79
+
80
+ def select(&block)
81
+ to_a.select(&block)
82
+ end
83
+
84
+ def eql?(other)
85
+ instance_of?(other.class) &&
86
+ @members.all? { |key| self[key].eql?(other[key]) }
87
+ end
88
+
89
+ def ==(other)
90
+ other = coerce(other).first if respond_to?(:coerce, true)
91
+ other.kind_of?(self.class) &&
92
+ @members.all? { |key| self[key] == other[key] }
93
+ end
94
+
95
+ def hash
96
+ self.class.hash +
97
+ to_a.each_with_index.map {|value, i| (i+1) * value.hash}.sum
98
+ end
99
+
100
+ if keyword_init
101
+ def initialize(struct_class_keyword_args = {})
102
+ members
103
+ @member_values = {}
104
+ struct_class_keyword_args.each do |attribute, value|
105
+ self[attribute] = value
106
+ end
107
+ end
108
+ else
109
+ def initialize(*attribute_values)
110
+ members
111
+ @member_values = {}
112
+ attribute_values.each_with_index do |value, i|
113
+ attribute = @members[i]
114
+ self[attribute] = value
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
120
+
121
+ ARG_VALIDATION = lambda do |class_name_or_attribute, *attributes|
122
+ class_name_or_attribute.nil? || attributes.any?(&:nil?)
123
+ end
124
+
125
+ CLASS_NAME_EXTRACTION = lambda do |class_name_or_attribute|
126
+ if class_name_or_attribute.is_a?(String)
127
+ raise NameError, "identifier name needs to be constant" unless class_name_or_attribute.match(/^[A-Z]/)
128
+ class_name_or_attribute
129
+ end
130
+ end
131
+
132
+ def new(class_name_or_attribute, *attributes, keyword_init: false)
133
+ raise 'Arguments cannot be nil' if ARG_VALIDATION[class_name_or_attribute, *attributes]
134
+ class_name = CLASS_NAME_EXTRACTION[class_name_or_attribute]
135
+ attributes.unshift(class_name_or_attribute) if class_name.nil?
136
+ attributes = attributes.map(&:to_sym)
137
+ struct_class = Class.new(&CLASS_DEFINITION_FOR_ATTRIBUTES[attributes, keyword_init])
138
+ class_name.nil? ? struct_class : const_set(class_name, struct_class)
139
+ end
140
+
141
+ end
142
+ end
metadata ADDED
@@ -0,0 +1,149 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pure-struct
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Andy Maleh
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-01-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 3.5.0
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 3.5.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: rdoc
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.12'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.12'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '1.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: juwelier
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 2.1.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 2.1.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.16.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.16.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: coveralls
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: puts_debuggerer
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
+ description: Pure Ruby re-implementation of Struct to ensure cross-Ruby functionality
112
+ where needed (e.g. Opal)
113
+ email: andy.am@gmail.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files:
117
+ - CHANGELOG.md
118
+ - LICENSE.txt
119
+ - README.md
120
+ files:
121
+ - CHANGELOG.md
122
+ - LICENSE.txt
123
+ - README.md
124
+ - VERSION
125
+ - lib/pure-struct.rb
126
+ homepage: http://github.com/AndyObtiva/pure-struct
127
+ licenses:
128
+ - MIT
129
+ metadata: {}
130
+ post_install_message:
131
+ rdoc_options: []
132
+ require_paths:
133
+ - lib
134
+ required_ruby_version: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ required_rubygems_version: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ requirements: []
145
+ rubygems_version: 3.1.4
146
+ signing_key:
147
+ specification_version: 4
148
+ summary: Pure Ruby Re-Implementation of Struct
149
+ test_files: []