u-struct 0.11.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|