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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b672fc8a3a469a1d00a066bbc9781acbfd0229e5acf40f4d05452a3db9bd6ff2
4
- data.tar.gz: 1fd9cdd284c43bbceb6b0bc44d21f358cc85d9fef1a5a3d6e9244529aa072279
3
+ metadata.gz: 9ba4dabf108cca13f77412fa1227a4227a02863d6eafc9d2dc4ef4a50260d537
4
+ data.tar.gz: 5226eff5e4088e2ec1756cf63de533e33ae57b7b57c651ffdc838777caabff04
5
5
  SHA512:
6
- metadata.gz: c85f28b501f523e3d541a19a64cc560f252ce72479e1df036b75c09dfec4d43843169a614922ce1aece40867434cd5b471aaa2e4eb37337f8694f38971dc491f
7
- data.tar.gz: a806cd4beb648c60e7e5ceed320ca63d0e9033b7d940fc14fbd0a3254b44b2a657704cf5ee82097aad991b11d7bf0285f99fa0bbe1946ecb5492e6f49f76fe1b
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
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Mangrove
5
- VERSION = "0.35.0"
5
+ VERSION = "0.37.0"
6
6
  end
data/lib/mangrove.rb CHANGED
@@ -8,6 +8,7 @@ require_relative "mangrove/option"
8
8
  require_relative "mangrove/result"
9
9
  require_relative "mangrove/enum"
10
10
  require_relative "mangrove/control_flow/control_signal"
11
+ require_relative "mangrove/try_from_ext"
11
12
 
12
13
  # Mangrove
13
14
  module Mangrove; end
@@ -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.35.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: 2025-01-21 00:00:00.000000000 Z
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.2
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: []