u-struct 0.11.0 → 1.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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +5 -5
- data/.rubocop.yml +129 -0
- data/.rubocop_todo.yml +10 -0
- data/.tool-versions +1 -0
- data/CHANGELOG.md +558 -13
- data/Gemfile +14 -3
- data/README.md +682 -16
- data/Rakefile +5 -5
- data/bin/console +3 -3
- data/bin/prepare_coverage +7 -9
- data/bin/run_ci +17 -0
- data/bin/tapioca +28 -0
- data/examples/rgb/number.rb +1 -1
- data/examples/rgb_1.rb +7 -6
- data/examples/rgb_2.rb +2 -2
- data/examples/rgb_3.rb +1 -1
- data/lib/micro/struct/factory/create_struct.rb +95 -69
- data/lib/micro/struct/factory/members.rb +1 -0
- data/lib/micro/struct/factory.rb +13 -4
- data/lib/micro/struct/features.rb +35 -16
- data/lib/micro/struct/normalize_names.rb +4 -3
- data/lib/micro/struct/version.rb +2 -1
- data/lib/micro/struct.rb +37 -5
- data/lib/u-struct.rb +2 -0
- data/rbi/micro/struct/factory/create_struct.rbi +60 -0
- data/rbi/micro/struct/factory/members.rbi +67 -0
- data/rbi/micro/struct/factory.rbi +41 -0
- data/rbi/micro/struct/features.rbi +41 -0
- data/rbi/micro/struct/normalize_names.rbi +20 -0
- data/rbi/micro/struct/version.rbi +3 -0
- data/rbi/micro/struct.rbi +68 -0
- data/sorbet/config +8 -0
- data/sorbet/rbi/gems/ast@2.4.2.rbi +54 -0
- data/sorbet/rbi/gems/coderay@1.1.3.rbi +8 -0
- data/sorbet/rbi/gems/diff-lcs@1.5.0.rbi +11 -0
- data/sorbet/rbi/gems/docile@1.4.0.rbi +54 -0
- data/sorbet/rbi/gems/method_source@1.0.0.rbi +8 -0
- data/sorbet/rbi/gems/minitest@5.15.0.rbi +345 -0
- data/sorbet/rbi/gems/parser@3.1.0.0.rbi +1196 -0
- data/sorbet/rbi/gems/pry@0.14.1.rbi +8 -0
- data/sorbet/rbi/gems/rake@13.0.6.rbi +806 -0
- data/sorbet/rbi/gems/rbi@0.0.9.rbi +1602 -0
- data/sorbet/rbi/gems/simplecov-html@0.12.3.rbi +89 -0
- data/sorbet/rbi/gems/simplecov@0.21.2.rbi +577 -0
- data/sorbet/rbi/gems/simplecov_json_formatter@0.1.3.rbi +8 -0
- data/sorbet/rbi/gems/spoom@1.1.8.rbi +1252 -0
- data/sorbet/rbi/gems/tapioca@0.6.2.rbi +1232 -0
- data/sorbet/rbi/gems/thor@1.2.1.rbi +844 -0
- data/sorbet/rbi/gems/unparser@0.6.3.rbi +8 -0
- data/sorbet/rbi/gems/webrick@1.7.0.rbi +601 -0
- data/sorbet/rbi/gems/yard-sorbet@0.6.1.rbi +199 -0
- data/sorbet/rbi/gems/yard@0.9.27.rbi +4112 -0
- data/sorbet/tapioca/config.yml +13 -0
- data/sorbet/tapioca/require.rb +4 -0
- data/u-struct.gemspec +3 -3
- metadata +38 -4
- data/bin/test +0 -8
data/Rakefile
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
require 'rake/testtask'
|
5
5
|
|
6
6
|
Rake::TestTask.new(:test) do |t|
|
7
|
-
t.libs <<
|
8
|
-
t.libs <<
|
9
|
-
t.test_files = FileList[
|
7
|
+
t.libs << 'test'
|
8
|
+
t.libs << 'lib'
|
9
|
+
t.test_files = FileList['test/**/*_test.rb']
|
10
10
|
end
|
11
11
|
|
12
12
|
task default: :test
|
data/bin/console
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require
|
5
|
-
require
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'micro/struct'
|
6
6
|
|
7
7
|
# You can add fixtures and/or initialization code here to make experimenting
|
8
8
|
# with your gem easier. You can also use a different console, if you like.
|
@@ -11,5 +11,5 @@ require "micro/struct"
|
|
11
11
|
# require "pry"
|
12
12
|
# Pry.start
|
13
13
|
|
14
|
-
require
|
14
|
+
require 'irb'
|
15
15
|
IRB.start(__FILE__)
|
data/bin/prepare_coverage
CHANGED
@@ -1,23 +1,21 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
|
+
|
3
4
|
# Borrowed from https://gist.github.com/qortex/7e7c49f3731391a91ee898336183acef
|
4
5
|
|
5
6
|
# Temporary hack to get CodeClimate to work with SimpleCov 0.18 JSON format until issue is fixed
|
6
7
|
# upstream: https://github.com/codeclimate/test-reporter/issues/413
|
7
8
|
|
8
|
-
require
|
9
|
+
require 'json'
|
9
10
|
|
10
|
-
filename =
|
11
|
+
filename = 'coverage/.resultset.json'
|
11
12
|
contents = JSON.parse(File.read(filename))
|
12
13
|
|
13
14
|
def remove_lines_key(obj)
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
end
|
19
|
-
else
|
20
|
-
obj
|
15
|
+
return obj unless obj.is_a?(Hash)
|
16
|
+
|
17
|
+
obj.transform_values do |val|
|
18
|
+
val.is_a?(Hash) && val.key?('lines') ? val['lines'] : remove_lines_key(val)
|
21
19
|
end
|
22
20
|
end
|
23
21
|
|
data/bin/run_ci
ADDED
data/bin/tapioca
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'tapioca' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require 'pathname'
|
12
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', Pathname.new(__FILE__).realpath)
|
13
|
+
|
14
|
+
bundle_binstub = File.expand_path('bundle', __dir__)
|
15
|
+
|
16
|
+
if File.file?(bundle_binstub)
|
17
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
18
|
+
load(bundle_binstub)
|
19
|
+
else
|
20
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
21
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
require 'rubygems'
|
26
|
+
require 'bundler/setup'
|
27
|
+
|
28
|
+
load Gem.bin_path('tapioca', 'tapioca')
|
data/examples/rgb/number.rb
CHANGED
data/examples/rgb_1.rb
CHANGED
@@ -6,12 +6,13 @@ gemfile do
|
|
6
6
|
source 'https://rubygems.org'
|
7
7
|
|
8
8
|
gem 'u-struct', path: '..'
|
9
|
-
gem 'kind'
|
10
9
|
end
|
11
10
|
|
12
11
|
RGBColor = Micro::Struct.with(:readonly, :to_ary).new(:red, :green, :blue) do
|
13
|
-
Number =
|
14
|
-
value.is_a?(::Integer) && value >= 0 && value <= 255
|
12
|
+
Number = ->(value) do
|
13
|
+
return value if value.is_a?(::Integer) && value >= 0 && value <= 255
|
14
|
+
|
15
|
+
raise TypeError.new("#{value} must be an Integer(>= 0 and <= 255)")
|
15
16
|
end
|
16
17
|
|
17
18
|
def initialize(r, g, b)
|
@@ -19,7 +20,7 @@ RGBColor = Micro::Struct.with(:readonly, :to_ary).new(:red, :green, :blue) do
|
|
19
20
|
end
|
20
21
|
|
21
22
|
def to_hex
|
22
|
-
'
|
23
|
+
format('#%<r>02x%<g>02x%<b>02x', r: red, g: green, b: blue)
|
23
24
|
end
|
24
25
|
end
|
25
26
|
|
@@ -48,6 +49,6 @@ puts
|
|
48
49
|
|
49
50
|
begin
|
50
51
|
RGBColor.new(red: 1, green: -1, blue: 255)
|
51
|
-
rescue => exception
|
52
|
-
puts exception #
|
52
|
+
rescue TypeError => exception
|
53
|
+
puts exception # TypeError (-1 must be an Integer(>= 0 and <= 255))
|
53
54
|
end
|
data/examples/rgb_2.rb
CHANGED
@@ -19,7 +19,7 @@ RGBNumber = Micro::Struct.with(:readonly).new(:value) do
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def to_s
|
22
|
-
'%02x'
|
22
|
+
format('%02x', value)
|
23
23
|
end
|
24
24
|
|
25
25
|
def inspect
|
@@ -70,6 +70,6 @@ puts
|
|
70
70
|
|
71
71
|
begin
|
72
72
|
RGBColor.new(r: 1, g: -1, b: 255)
|
73
|
-
rescue => exception
|
73
|
+
rescue Kind::Error => exception
|
74
74
|
puts exception # Kind::Error (-1 expected to be a kind of Integer(>= 0 and <= 255))
|
75
75
|
end
|
data/examples/rgb_3.rb
CHANGED
@@ -1,88 +1,114 @@
|
|
1
|
+
# typed: true
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
|
-
|
4
|
-
|
5
|
-
|
4
|
+
module Micro::Struct
|
5
|
+
class Factory
|
6
|
+
module CreateStruct
|
7
|
+
extend self
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
+
def with(members, features, struct_block)
|
10
|
+
struct = create_struct(members)
|
9
11
|
|
10
|
-
|
11
|
-
ClassScope.def_to_proc(struct) if features[:to_proc]
|
12
|
-
ClassScope.def_private_writers(struct) if features[:readonly]
|
12
|
+
ClassScope.def_new(struct, members)
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
ClassScope.def_features(struct, features) if features.is_a?(Features::Exposed)
|
15
|
+
ClassScope.def_to_proc(struct) if features.option?(:to_proc)
|
16
|
+
ClassScope.def_private_writers(struct) if features.option?(:readonly)
|
17
17
|
|
18
|
-
|
18
|
+
InstanceScope.def_with(struct) if features.option?(:instance_copy)
|
19
|
+
InstanceScope.def_to_ary(struct) if features.option?(:to_ary)
|
20
|
+
InstanceScope.def_to_hash(struct) if features.option?(:to_hash)
|
19
21
|
|
20
|
-
|
21
|
-
end
|
22
|
+
ClassScope.evaluate(struct, struct_block)
|
22
23
|
|
23
|
-
|
24
|
-
def self.def_new(struct, members)
|
25
|
-
# The .new() method will require all required keyword arguments.
|
26
|
-
# We are doing this because the Struct constructor keyword init option treats everything as optional.
|
27
|
-
#
|
28
|
-
struct.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
29
|
-
class << self
|
30
|
-
undef_method :new
|
31
|
-
|
32
|
-
def new(#{members.to_eval.keyword_args}) # def new(a:, b:, c: nil) do
|
33
|
-
instance = allocate # instance = allocate
|
34
|
-
instance.send(:initialize, #{members.to_eval.positional_args}) # instance.send(:initialize, a, b, c)
|
35
|
-
instance # instance
|
36
|
-
end # end
|
37
|
-
|
38
|
-
alias __new__ new
|
39
|
-
end
|
40
|
-
RUBY
|
24
|
+
struct
|
41
25
|
end
|
42
26
|
|
43
|
-
|
44
|
-
struct.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
45
|
-
def self.to_proc
|
46
|
-
->(hash) { new(**hash) }
|
47
|
-
end
|
48
|
-
RUBY
|
49
|
-
end
|
27
|
+
private
|
50
28
|
|
51
|
-
def
|
52
|
-
|
29
|
+
def create_struct(members)
|
30
|
+
::Struct.new(*members.required_and_optional)
|
53
31
|
end
|
54
32
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
33
|
+
module ClassScope
|
34
|
+
def self.def_new(struct, members)
|
35
|
+
# The .new() method will require all required keyword arguments.
|
36
|
+
# We are doing this because the Struct constructor keyword init option treats everything as optional.
|
37
|
+
#
|
38
|
+
struct.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
39
|
+
class << self
|
40
|
+
undef_method :new
|
41
|
+
|
42
|
+
def new(#{members.to_eval.keyword_args}) # def new(a:, b:, c: nil) do
|
43
|
+
instance = allocate # instance = allocate
|
44
|
+
instance.send(:initialize, #{members.to_eval.positional_args}) # instance.send(:initialize, a, b, c)
|
45
|
+
instance # instance
|
46
|
+
end # end
|
47
|
+
|
48
|
+
alias __new__ new
|
49
|
+
end
|
50
|
+
RUBY
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.def_features(struct, features)
|
54
|
+
struct.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
55
|
+
class << self
|
56
|
+
attr_accessor :__features__
|
57
|
+
|
58
|
+
alias features __features__
|
59
|
+
end
|
60
|
+
RUBY
|
61
|
+
|
62
|
+
struct.__features__ = features
|
63
|
+
|
64
|
+
struct.send(:private_class_method, :__features__=)
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.def_to_proc(struct)
|
68
|
+
struct.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
69
|
+
def self.to_proc
|
70
|
+
->(hash) { new(**hash) }
|
71
|
+
end
|
72
|
+
RUBY
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.def_private_writers(struct)
|
76
|
+
struct.send(:private, :[]=)
|
77
|
+
struct.members.each { |member| struct.send(:private, "#{member}=") }
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.evaluate(struct, block)
|
81
|
+
struct.class_eval(&block) if block
|
82
|
+
end
|
67
83
|
end
|
68
84
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
85
|
+
module InstanceScope
|
86
|
+
def self.def_to_ary(struct)
|
87
|
+
struct.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
88
|
+
def to_ary
|
89
|
+
to_a
|
90
|
+
end
|
91
|
+
RUBY
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.def_to_hash(struct)
|
95
|
+
struct.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
96
|
+
def to_hash
|
97
|
+
to_h
|
98
|
+
end
|
99
|
+
RUBY
|
100
|
+
end
|
101
|
+
|
102
|
+
def self.def_with(struct)
|
103
|
+
struct.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
104
|
+
def with(**members)
|
105
|
+
self.class.new(**to_h.merge(members))
|
106
|
+
end
|
107
|
+
RUBY
|
108
|
+
end
|
83
109
|
end
|
84
110
|
end
|
85
|
-
end
|
86
111
|
|
87
|
-
|
112
|
+
private_constant :CreateStruct
|
113
|
+
end
|
88
114
|
end
|
data/lib/micro/struct/factory.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# typed: true
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module Micro::Struct
|
@@ -5,14 +6,22 @@ module Micro::Struct
|
|
5
6
|
require_relative 'factory/members'
|
6
7
|
require_relative 'factory/create_struct'
|
7
8
|
|
8
|
-
def initialize(
|
9
|
-
@features = Features.
|
9
|
+
def initialize(feature_names)
|
10
|
+
@features = Features.config(feature_names)
|
10
11
|
end
|
11
12
|
|
12
|
-
def
|
13
|
+
def __create__(required_members, required, optional, struct_block) # :nodoc:
|
13
14
|
members = Members.new(required_members, required, optional)
|
14
15
|
|
15
|
-
CreateStruct.with(members,
|
16
|
+
CreateStruct.with(members, @features, struct_block)
|
17
|
+
end
|
18
|
+
|
19
|
+
def new(*required_members, required: nil, optional: nil, &struct_block)
|
20
|
+
__create__(required_members, required, optional, struct_block)
|
21
|
+
end
|
22
|
+
|
23
|
+
def instance(**members, &block)
|
24
|
+
__create__(members.keys, nil, nil, block).new(**members)
|
16
25
|
end
|
17
26
|
end
|
18
27
|
|
@@ -1,30 +1,49 @@
|
|
1
|
+
# typed: true
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module Micro::Struct
|
4
5
|
module Features
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
6
|
+
module Options
|
7
|
+
def self.from(names:)
|
8
|
+
options = names.each_with_object({}) { |name, memo| memo[name] = true }
|
9
|
+
|
10
|
+
{
|
11
|
+
to_ary: options.fetch(:to_ary, false),
|
12
|
+
to_hash: options.fetch(:to_hash, false),
|
13
|
+
to_proc: options.fetch(:to_proc, false),
|
14
|
+
readonly: options.fetch(:readonly, false),
|
15
|
+
instance_copy: options.fetch(:instance_copy, false),
|
16
|
+
exposed_features: options.fetch(:exposed_features, false)
|
17
|
+
}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
Config = ::Struct.new(:names, :options) do
|
22
|
+
def option?(name)
|
23
|
+
options.fetch(name)
|
24
|
+
end
|
25
|
+
|
26
|
+
def options?(*names)
|
27
|
+
names.all? { |name| option?(name) }
|
28
|
+
end
|
18
29
|
end
|
19
30
|
|
31
|
+
Exposed = Class.new(Config)
|
32
|
+
|
20
33
|
Names = ->(values) do
|
21
34
|
NormalizeNames::AsSymbols.(values, context: 'feature')
|
22
35
|
end
|
23
36
|
|
24
|
-
def self.
|
25
|
-
|
37
|
+
def self.config(values)
|
38
|
+
names = Names[values]
|
39
|
+
options = Options.from(names: names)
|
40
|
+
|
41
|
+
return Config.new(names, options) unless options[:exposed_features]
|
42
|
+
|
43
|
+
names.delete(:exposed_features)
|
44
|
+
options.delete(:exposed_features)
|
26
45
|
|
27
|
-
|
46
|
+
Exposed.new(names.freeze, options.freeze).freeze
|
28
47
|
end
|
29
48
|
end
|
30
49
|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# typed: true
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module Micro::Struct
|
@@ -5,10 +6,10 @@ module Micro::Struct
|
|
5
6
|
module AsSymbols
|
6
7
|
REGEXP = /\A[_A-Za-z]\w*\z/.freeze
|
7
8
|
Invalid = ->(context, val) { raise NameError.new("invalid #{context} name: #{val}") }
|
8
|
-
AsSymbol = ->(context, val) { REGEXP =~ val ? val.to_sym : Invalid[context, val] }
|
9
|
+
AsSymbol = ->(context, val) { REGEXP =~ val ? val.to_sym : Invalid[context, val] }
|
9
10
|
|
10
|
-
def self.call(
|
11
|
-
Array(
|
11
|
+
def self.call(arg, context:)
|
12
|
+
Array(arg).map { |values| AsSymbol[context, values] }
|
12
13
|
end
|
13
14
|
end
|
14
15
|
end
|
data/lib/micro/struct/version.rb
CHANGED
data/lib/micro/struct.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# typed: true
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require_relative 'struct/version'
|
@@ -31,13 +32,14 @@ module Micro
|
|
31
32
|
# Micro::Struct.new(:name) {}
|
32
33
|
#
|
33
34
|
# Available features (use one, many, or all) to create Structs with a special behavior:
|
34
|
-
# .with(:to_ary, :to_hash, :to_proc, :readonly, :instance_copy)
|
35
|
+
# .with(:to_ary, :to_hash, :to_proc, :readonly, :instance_copy, :exposed_features)
|
35
36
|
#
|
36
37
|
# Micro::Struct.with(:to_ary).new(:name)
|
37
38
|
# Micro::Struct.with(:to_ary, :to_hash).new(:name)
|
38
39
|
# Micro::Struct.with(:to_ary, :to_hash, :to_proc).new(:name)
|
39
40
|
# Micro::Struct.with(:to_ary, :to_hash, :to_proc, :readonly).new(:name)
|
40
41
|
# Micro::Struct.with(:to_ary, :to_hash, :to_proc, :readonly, :instance_copy).new(:name)
|
42
|
+
# Micro::Struct.with(:to_ary, :to_hash, :to_proc, :readonly, :instance_copy, :exposed_features).new(:name)
|
41
43
|
#
|
42
44
|
# All of the possible combinations to create a Ruby Struct. ;)
|
43
45
|
#
|
@@ -57,12 +59,42 @@ module Micro
|
|
57
59
|
#
|
58
60
|
# Micro::Struct.with(*features).new(...) {}
|
59
61
|
module Struct
|
60
|
-
|
61
|
-
|
62
|
+
extend self
|
63
|
+
|
64
|
+
def with(*feature_names)
|
65
|
+
factory(feature_names)
|
66
|
+
end
|
67
|
+
|
68
|
+
alias_method :[], :with
|
69
|
+
|
70
|
+
def new(*members, required: nil, optional: nil, &block)
|
71
|
+
with.__create__(members, required, optional, block)
|
72
|
+
end
|
73
|
+
|
74
|
+
def instance(**members, &block)
|
75
|
+
with.instance(**members, &block)
|
76
|
+
end
|
77
|
+
|
78
|
+
READONLY = [:readonly].freeze
|
79
|
+
IMMUTABLE = [:readonly, :instance_copy].freeze
|
80
|
+
EMPTY_ARRAY = [].freeze
|
81
|
+
|
82
|
+
def readonly(with: EMPTY_ARRAY)
|
83
|
+
factory(with, READONLY)
|
62
84
|
end
|
63
85
|
|
64
|
-
def
|
65
|
-
|
86
|
+
def immutable(with: EMPTY_ARRAY)
|
87
|
+
factory(with, IMMUTABLE)
|
66
88
|
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def factory(names, defaults = EMPTY_ARRAY)
|
93
|
+
features = ::Kernel.Array(names)
|
94
|
+
|
95
|
+
Factory.new(defaults.empty? ? features : defaults + features)
|
96
|
+
end
|
97
|
+
|
98
|
+
private_constant :READONLY, :IMMUTABLE, :EMPTY_ARRAY
|
67
99
|
end
|
68
100
|
end
|
data/lib/u-struct.rb
CHANGED
@@ -0,0 +1,60 @@
|
|
1
|
+
# typed: true
|
2
|
+
|
3
|
+
module Micro::Struct::Factory::CreateStruct
|
4
|
+
extend self
|
5
|
+
|
6
|
+
STRUCT_BLOCK = T.type_alias { T.nilable(T.proc.params(arg0: T.untyped).returns(T.untyped)) }
|
7
|
+
STRUCT_MEMBERS = T.type_alias { Micro::Struct::Factory::Members }
|
8
|
+
FEATURES_EXPOSED = T.type_alias { Micro::Struct::Features::Exposed }
|
9
|
+
FEATURES_CONFIG = T.type_alias { T.any(Micro::Struct::Features::Config, FEATURES_EXPOSED) }
|
10
|
+
|
11
|
+
sig {
|
12
|
+
params(
|
13
|
+
members: STRUCT_MEMBERS,
|
14
|
+
features: FEATURES_CONFIG,
|
15
|
+
struct_block: STRUCT_BLOCK
|
16
|
+
).returns(T.class_of(Struct))
|
17
|
+
}
|
18
|
+
def with(members, features, struct_block)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def create_struct(members); end
|
24
|
+
|
25
|
+
module ClassScope
|
26
|
+
sig { params(struct: T.class_of(Struct), members: STRUCT_MEMBERS).void }
|
27
|
+
def self.def_new(struct, members)
|
28
|
+
end
|
29
|
+
|
30
|
+
sig { params(struct: T.untyped, features: FEATURES_EXPOSED).void }
|
31
|
+
def self.def_features(struct, features)
|
32
|
+
end
|
33
|
+
|
34
|
+
sig { params(struct: T.class_of(Struct)).void }
|
35
|
+
def self.def_to_proc(struct)
|
36
|
+
end
|
37
|
+
|
38
|
+
sig { params(struct: T.class_of(Struct)).void }
|
39
|
+
def self.def_private_writers(struct)
|
40
|
+
end
|
41
|
+
|
42
|
+
sig { params(struct: T.class_of(Struct), block: STRUCT_BLOCK).void }
|
43
|
+
def self.evaluate(struct, block)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
module InstanceScope
|
48
|
+
sig { params(struct: T.class_of(Struct)).void }
|
49
|
+
def self.def_to_ary(struct)
|
50
|
+
end
|
51
|
+
|
52
|
+
sig { params(struct: T.class_of(Struct)).void }
|
53
|
+
def self.def_to_hash(struct)
|
54
|
+
end
|
55
|
+
|
56
|
+
sig { params(struct: T.class_of(Struct)).void }
|
57
|
+
def self.def_with(struct)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|