mangrove 0.35.0 → 0.37.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/.rubocop.yml +4 -0
- data/README.md +0 -1
- data/lib/mangrove/enum.rb +40 -0
- data/lib/mangrove/try_from_ext.rb +41 -0
- data/lib/mangrove/version.rb +1 -1
- data/lib/mangrove.rb +1 -0
- data/lib/tapioca/dsl/compilers/mangrove_enum.rb +3 -0
- data/lib/tapioca/dsl/compilers/mangrove_try_from_ext.rb +33 -0
- data/sorbet/rbi/dsl/.gitattributes +1 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9ba4dabf108cca13f77412fa1227a4227a02863d6eafc9d2dc4ef4a50260d537
|
4
|
+
data.tar.gz: 5226eff5e4088e2ec1756cf63de533e33ae57b7b57c651ffdc838777caabff04
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 714d9322edd6cc20354b271f1659e0b623b8ecf1336137b493bb501ed4d884115aeee98bbc83a18f1bdad678cf3842a02ae9df09b3975b4bc9c2c169230d3b5f
|
7
|
+
data.tar.gz: e939ae71645f893fe28e93364978081508f7b2ae73dc86eb168b46a7e28d87b4100a5245eaf3d1af6ce96fee6b42fb024c695b113bea8a6edd47b516acab2b58
|
data/.rubocop.yml
CHANGED
@@ -31,6 +31,9 @@ Metrics/ModuleLength:
|
|
31
31
|
Naming/BlockForwarding:
|
32
32
|
EnforcedStyle: explicit
|
33
33
|
|
34
|
+
Naming/MethodParameterName:
|
35
|
+
Enabled: false
|
36
|
+
|
34
37
|
Naming/VariableNumber:
|
35
38
|
EnforcedStyle: snake_case
|
36
39
|
|
@@ -64,3 +67,4 @@ Style/StringLiterals:
|
|
64
67
|
Style/StringLiteralsInInterpolation:
|
65
68
|
Enabled: true
|
66
69
|
EnforcedStyle: double_quotes
|
70
|
+
|
data/README.md
CHANGED
@@ -17,7 +17,6 @@ Mangrove is a Ruby toolkit that brings a functional, statically-typed flavor to
|
|
17
17
|
|
18
18
|
- **Enums (ADTs)**
|
19
19
|
Define your own sealed enums with typed variants. Each variant can hold distinct inner data.
|
20
|
-
|
21
20
|
- **Functional Patterns**
|
22
21
|
Chain transformations or short-circuit error handling with a clean monadic style.
|
23
22
|
|
data/lib/mangrove/enum.rb
CHANGED
@@ -51,6 +51,35 @@ module Mangrove
|
|
51
51
|
T.cast(self, \#{caller.send(:binding).receiver.name})
|
52
52
|
end
|
53
53
|
|
54
|
+
def serialize(inner_serialization_methods: [:serialize, :to_h])
|
55
|
+
serialized_inner = begin
|
56
|
+
serialized_klass = [
|
57
|
+
Hash,
|
58
|
+
String,
|
59
|
+
Numeric,
|
60
|
+
TrueClass,
|
61
|
+
FalseClass,
|
62
|
+
NilClass
|
63
|
+
]
|
64
|
+
|
65
|
+
if serialized_klass.any? { |klass| @inner.is_a?(klass) }
|
66
|
+
@inner
|
67
|
+
else
|
68
|
+
inner_serialization_methods.find do |method_name|
|
69
|
+
if @inner.respond_to?(method_name, true)
|
70
|
+
maybe_hash = @inner.send(method_name)
|
71
|
+
|
72
|
+
if maybe_hash.is_a?(Hash)
|
73
|
+
break maybe_hash
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
{ type: self.class.name, value: serialized_inner }
|
81
|
+
end
|
82
|
+
|
54
83
|
def ==(other)
|
55
84
|
other.is_a?(self.class) && other.inner == @inner
|
56
85
|
end
|
@@ -93,6 +122,17 @@ module Mangrove
|
|
93
122
|
extend T::Helpers
|
94
123
|
|
95
124
|
abstract!
|
125
|
+
|
126
|
+
def self.deserialize(hash)
|
127
|
+
klass = const_get(hash[:type] || hash["type"])
|
128
|
+
value = hash[:value] || hash["value"]
|
129
|
+
|
130
|
+
begin
|
131
|
+
klass.new(value)
|
132
|
+
rescue TypeError
|
133
|
+
klass.new(klass.deserialize(value))
|
134
|
+
end
|
135
|
+
end
|
96
136
|
RUBY
|
97
137
|
|
98
138
|
receiver.class_eval(code)
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Mangrove
|
5
|
+
module TryFromExt
|
6
|
+
extend T::Sig
|
7
|
+
extend T::Helpers
|
8
|
+
|
9
|
+
include Kernel
|
10
|
+
|
11
|
+
sig {
|
12
|
+
type_parameters(:I, :O, :E)
|
13
|
+
.params(
|
14
|
+
from: T::Class[T.type_parameter(:I)],
|
15
|
+
to: T::Class[T.type_parameter(:O)],
|
16
|
+
err: T::Class[T.type_parameter(:E)],
|
17
|
+
block: T.proc.params(arg: T.type_parameter(:I)).returns(Mangrove::Result[T.type_parameter(:O), T.type_parameter(:E)])
|
18
|
+
).void
|
19
|
+
}
|
20
|
+
# rubocop:disable Lint/UnusedMethodArgument
|
21
|
+
def try_convert_from(from:, to:, err:, &block)
|
22
|
+
T.bind(self, T::Class[T.type_parameter(:O)])
|
23
|
+
|
24
|
+
vars = from.instance_variable_get(:@convertable_to) || {}
|
25
|
+
vars[self] = block
|
26
|
+
from.instance_variable_set(:@convertable_to, vars)
|
27
|
+
|
28
|
+
@convertable_from ||= {}
|
29
|
+
@convertable_from[from] = [err, block]
|
30
|
+
|
31
|
+
into_t = T.cast(self, Class)
|
32
|
+
|
33
|
+
from.define_method("try_into_#{T.must_because(into_t.name) { "name is required" }.gsub(/::|([A-Z]+)([A-Z][a-z])/, '\1_\2').gsub(/([a-z\d])([A-Z])/, '\1_\2').downcase}") do
|
34
|
+
proc = T.unsafe(self).class.ancestors.lazy.map { |klass| klass.instance_variable_get(:@convertable_to)&.[](into_t) }.find(&:itself)
|
35
|
+
|
36
|
+
proc.call(self)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
# rubocop:enable Lint/UnusedMethodArgument
|
40
|
+
end
|
41
|
+
end
|
data/lib/mangrove/version.rb
CHANGED
data/lib/mangrove.rb
CHANGED
@@ -40,6 +40,7 @@ module Tapioca
|
|
40
40
|
inner_type = runtime_type_to_type_name(variant.instance_variable_get(:@__mangrove__enum_inner_type))
|
41
41
|
constant_type.create_class(variant.name.gsub(/.*::/, ""), superclass_name: constant_type.fully_qualified_name) { |variant_type|
|
42
42
|
variant_type.create_method("initialize", parameters: [create_param("inner", type: inner_type)], return_type: "void")
|
43
|
+
variant_type.create_method("serialize", parameters: [create_param("inner_serialization_methods", type: "T.nilable(T::Array[Symbol])")], return_type: "T::Hash[Symbol, T.untyped]")
|
43
44
|
variant_type.create_method("inner", return_type: inner_type)
|
44
45
|
variant_type.create_method("as_super", return_type: constant.name.to_s)
|
45
46
|
variant_type.sort_nodes!
|
@@ -55,6 +56,8 @@ module Tapioca
|
|
55
56
|
end
|
56
57
|
|
57
58
|
constant_type.create_method("inner", return_type:)
|
59
|
+
constant_type.create_method("serialize", parameters: [create_param("inner_serialization_methods", type: "T.nilable(T::Array[Symbol])")], return_type: "T::Hash[Symbol, T.untyped]")
|
60
|
+
constant_type.create_method("deserialize", parameters: [create_param("hash", type: "T::Hash[T.any(Symbol, String), T.untyped]")], return_type: constant.name)
|
58
61
|
constant_type.create_method("as_super", return_type: constant.name.to_s)
|
59
62
|
constant_type.sort_nodes!
|
60
63
|
}
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "mangrove/try_from_ext"
|
5
|
+
require "tapioca/dsl"
|
6
|
+
require "sorbet-runtime"
|
7
|
+
|
8
|
+
module Tapioca
|
9
|
+
module Compilers
|
10
|
+
class TryFromExt < Tapioca::Dsl::Compiler
|
11
|
+
extend T::Sig
|
12
|
+
|
13
|
+
ConstantType = type_member { { fixed: T.class_of(Mangrove::TryFromExt) } }
|
14
|
+
|
15
|
+
sig { override.returns(T::Enumerable[Module]) }
|
16
|
+
def self.gather_constants
|
17
|
+
all_classes.select { |c| c.singleton_class < ::Mangrove::TryFromExt }
|
18
|
+
end
|
19
|
+
|
20
|
+
sig { override.void }
|
21
|
+
def decorate
|
22
|
+
return if constant.instance_variable_get(:@convertable_from).nil? || constant.instance_variable_get(:@convertable_from).empty?
|
23
|
+
|
24
|
+
constant.instance_variable_get(:@convertable_from)&.each do |convertable_from, values|
|
25
|
+
err_constant, _block = values
|
26
|
+
root.create_path(convertable_from) do |klass|
|
27
|
+
klass.create_method("try_into_#{constant.to_s.gsub(/::|([A-Z]+)([A-Z][a-z])/, '\1_\2').gsub(/([a-z\d])([A-Z])/, '\1_\2').downcase}", return_type: "Mangrove::Result[#{constant}, #{err_constant}]")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
**/*.rbi linguist-generated=true
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mangrove
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.37.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kazuma Murata
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: sorbet-runtime
|
@@ -47,14 +47,17 @@ files:
|
|
47
47
|
- lib/mangrove/result.rb
|
48
48
|
- lib/mangrove/result/control_signal.rb
|
49
49
|
- lib/mangrove/result/ext.rb
|
50
|
+
- lib/mangrove/try_from_ext.rb
|
50
51
|
- lib/mangrove/version.rb
|
51
52
|
- lib/tapioca/dsl/compilers/mangrove_enum.rb
|
52
53
|
- lib/tapioca/dsl/compilers/mangrove_result_ext.rb
|
54
|
+
- lib/tapioca/dsl/compilers/mangrove_try_from_ext.rb
|
53
55
|
- rbi/mangrove.rbi
|
54
56
|
- sig/mangrove.rbs
|
55
57
|
- sorbet/config
|
56
58
|
- sorbet/rbi/annotations/.gitattributes
|
57
59
|
- sorbet/rbi/annotations/rainbow.rbi
|
60
|
+
- sorbet/rbi/dsl/.gitattributes
|
58
61
|
- sorbet/rbi/gems/.gitattributes
|
59
62
|
- sorbet/rbi/gems/ast@2.4.2.rbi
|
60
63
|
- sorbet/rbi/gems/benchmark@0.4.0.rbi
|
@@ -132,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
132
135
|
- !ruby/object:Gem::Version
|
133
136
|
version: '0'
|
134
137
|
requirements: []
|
135
|
-
rubygems_version: 3.6.
|
138
|
+
rubygems_version: 3.6.9
|
136
139
|
specification_version: 4
|
137
140
|
summary: Toolkit for leveraging Sorbet's type system.
|
138
141
|
test_files: []
|