literal 1.5.0 → 1.7.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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/lib/literal/array.rb +15 -15
  3. data/lib/literal/data_structure.rb +4 -3
  4. data/lib/literal/delegator.rb +25 -0
  5. data/lib/literal/enum.rb +4 -5
  6. data/lib/literal/flags/flags_16.rb +7 -0
  7. data/lib/literal/flags/flags_32.rb +7 -0
  8. data/lib/literal/flags/flags_64.rb +7 -0
  9. data/lib/literal/flags/flags_8.rb +7 -0
  10. data/lib/literal/flags.rb +0 -24
  11. data/lib/literal/hash.rb +1 -1
  12. data/lib/literal/properties/schema.rb +3 -3
  13. data/lib/literal/properties.rb +5 -6
  14. data/lib/literal/property.rb +3 -3
  15. data/lib/literal/rails/enum_type.rb +4 -0
  16. data/lib/literal/rails.rb +0 -3
  17. data/lib/literal/set.rb +1 -1
  18. data/lib/literal/transforms.rb +2 -2
  19. data/lib/literal/tuple.rb +2 -2
  20. data/lib/literal/types/array_type.rb +1 -0
  21. data/lib/literal/types/class_type.rb +3 -2
  22. data/lib/literal/types/constraint_type.rb +5 -4
  23. data/lib/literal/{deferred_type.rb → types/deferred_type.rb} +1 -1
  24. data/lib/literal/types/descendant_type.rb +2 -1
  25. data/lib/literal/types/enumerable_type.rb +2 -1
  26. data/lib/literal/types/frozen_type.rb +3 -2
  27. data/lib/literal/types/hash_type.rb +3 -2
  28. data/lib/literal/types/interface_type.rb +20 -14
  29. data/lib/literal/types/intersection_type.rb +4 -3
  30. data/lib/literal/types/map_type.rb +2 -1
  31. data/lib/literal/types/nilable_type.rb +3 -2
  32. data/lib/literal/types/not_type.rb +4 -3
  33. data/lib/literal/types/predicate_type.rb +22 -0
  34. data/lib/literal/types/range_type.rb +2 -1
  35. data/lib/literal/types/set_type.rb +2 -1
  36. data/lib/literal/types/tuple_type.rb +1 -0
  37. data/lib/literal/types/union_type.rb +46 -30
  38. data/lib/literal/types.rb +143 -87
  39. data/lib/literal/value.rb +65 -0
  40. data/lib/literal/version.rb +1 -1
  41. data/lib/literal.rb +82 -37
  42. metadata +26 -5
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Literal::Value
4
+ def self.to_proc
5
+ -> (value) { new(value) }
6
+ end
7
+
8
+ def self.[](value)
9
+ new(value)
10
+ end
11
+
12
+ def self.from_pack(payload)
13
+ object = allocate
14
+ object.marshal_load(payload)
15
+ object
16
+ end
17
+
18
+ # Takes a list of method names and delegates them to the underlying value.
19
+ def self.delegate(*methods)
20
+ methods.each do |method_name|
21
+ class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
22
+ # frozen_string_literal: true
23
+
24
+ def #{method_name}(...)
25
+ @value.#{method_name}(...)
26
+ end
27
+ RUBY
28
+ end
29
+ end
30
+
31
+ def initialize(value)
32
+ Literal.check(value, __type__)
33
+ @value = value
34
+ freeze
35
+ end
36
+
37
+ attr_reader :value
38
+
39
+ def inspect
40
+ "#{self.class.name}(#{value.inspect})"
41
+ end
42
+
43
+ def ===(other)
44
+ self.class === other && @value == other.value
45
+ end
46
+
47
+ alias_method :==, :===
48
+
49
+ def as_pack
50
+ marshal_dump
51
+ end
52
+
53
+ def marshal_load(payload)
54
+ _version, value, was_frozen = payload
55
+
56
+ @value = value
57
+ freeze if was_frozen
58
+ end
59
+
60
+ def marshal_dump
61
+ [1, @value, frozen?].freeze
62
+ end
63
+
64
+ freeze
65
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Literal
4
- VERSION = "1.5.0"
4
+ VERSION = "1.7.0"
5
5
  end
data/lib/literal.rb CHANGED
@@ -1,33 +1,55 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "zeitwerk"
4
+ require_relative "literal/version"
5
+
3
6
  module Literal
4
- autoload :Array, "literal/array"
5
- autoload :Data, "literal/data"
6
- autoload :DataProperty, "literal/data_property"
7
- autoload :DataStructure, "literal/data_structure"
8
- autoload :Enum, "literal/enum"
9
- autoload :Flags, "literal/flags"
10
- autoload :Flags16, "literal/flags"
11
- autoload :Flags32, "literal/flags"
12
- autoload :Flags64, "literal/flags"
13
- autoload :Flags8, "literal/flags"
14
- autoload :Hash, "literal/hash"
15
- autoload :Null, "literal/null"
16
- autoload :Object, "literal/object"
17
- autoload :Properties, "literal/properties"
18
- autoload :Property, "literal/property"
19
- autoload :Set, "literal/set"
20
- autoload :Struct, "literal/struct"
21
- autoload :Type, "literal/type"
22
- autoload :Types, "literal/types"
23
- autoload :Tuple, "literal/tuple"
24
-
25
- # Errors
26
- autoload :Error, "literal/errors/error"
27
- autoload :TypeError, "literal/errors/type_error"
28
- autoload :ArgumentError, "literal/errors/argument_error"
29
-
30
- autoload :TRANSFORMS, "literal/transforms"
7
+ Loader = Zeitwerk::Loader.for_gem.tap do |loader|
8
+ loader.inflector.inflect(
9
+ "json_data_type" => "JSONDataType"
10
+ )
11
+
12
+ loader.collapse("#{__dir__}/literal/flags")
13
+ loader.collapse("#{__dir__}/literal/errors")
14
+
15
+ loader.setup
16
+ end
17
+
18
+ def self.Value(*args, **kwargs, &block)
19
+ value_class = Class.new(Literal::Value)
20
+
21
+ type = Literal::Types._Constraint(*args, **kwargs)
22
+ value_class.define_method(:__type__) { type }
23
+
24
+ if subtype?(type, Integer)
25
+ value_class.alias_method :to_i, :value
26
+ elsif subtype?(type, String)
27
+ value_class.alias_method :to_s, :value
28
+ value_class.alias_method :to_str, :value
29
+ elsif subtype?(type, Array)
30
+ value_class.alias_method :to_a, :value
31
+ value_class.alias_method :to_ary, :value
32
+ elsif subtype?(type, Hash)
33
+ value_class.alias_method :to_h, :value
34
+ elsif subtype?(type, Float)
35
+ value_class.alias_method :to_f, :value
36
+ elsif subtype?(type, Set)
37
+ value_class.alias_method :to_set, :value
38
+ end
39
+
40
+ value_class.class_eval(&block) if block
41
+ value_class.freeze
42
+ end
43
+
44
+ def self.Delegator(*args, **kwargs, &block)
45
+ delegator_class = Class.new(Literal::Delegator)
46
+
47
+ type = Literal::Types._Constraint(*args, **kwargs)
48
+ delegator_class.define_method(:__type__) { type }
49
+
50
+ delegator_class.class_eval(&block) if block
51
+ delegator_class.freeze
52
+ end
31
53
 
32
54
  def self.Enum(type)
33
55
  Class.new(Literal::Enum) do
@@ -51,27 +73,50 @@ module Literal
51
73
  Literal::Tuple::Generic.new(*types)
52
74
  end
53
75
 
54
- def self.check(actual:, expected:)
55
- if expected === actual
76
+ def self.Brand(...)
77
+ Literal::Brand.new(...)
78
+ end
79
+
80
+ def self.check(value, type)
81
+ if type === value
56
82
  true
57
83
  else
58
- context = Literal::TypeError::Context.new(expected:, actual:)
59
- expected.record_literal_type_errors(context) if expected.respond_to?(:record_literal_type_errors)
84
+ context = Literal::TypeError::Context.new(expected: type, actual: value)
85
+ type.record_literal_type_errors(context) if type.respond_to?(:record_literal_type_errors)
60
86
  yield context if block_given?
61
87
  raise Literal::TypeError.new(context:)
62
88
  end
63
89
  end
64
90
 
65
- def self.subtype?(type, of:)
66
- type = type.block.call if Types::DeferredType === type
91
+ def self.subtype?(type, supertype)
92
+ subtype = type
93
+
94
+ subtype = subtype.block.call if Types::DeferredType === subtype
95
+
96
+ return true if supertype == subtype
67
97
 
68
- (of == type) || case of
98
+ case supertype
69
99
  when Literal::Type
70
- of >= type
100
+ supertype >= subtype
71
101
  when Module
72
- (Module === type) ? of >= type : false
102
+ case subtype
103
+ when Module
104
+ supertype >= subtype
105
+ when Numeric
106
+ Numeric >= supertype
107
+ when String
108
+ String >= supertype
109
+ when Symbol
110
+ Symbol >= supertype
111
+ when ::Array
112
+ ::Array >= supertype
113
+ when ::Hash
114
+ ::Hash >= supertype
115
+ else
116
+ false
117
+ end
73
118
  when Range
74
- of.cover?(type)
119
+ supertype.cover?(subtype)
75
120
  else
76
121
  false
77
122
  end
metadata CHANGED
@@ -1,14 +1,28 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: literal
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joel Drapper
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-01-17 00:00:00.000000000 Z
11
- dependencies: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: zeitwerk
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '0'
12
26
  description: Enums, properties, generics, structured objects and runtime type checking.
13
27
  email:
14
28
  - joel@drapper.me
@@ -22,13 +36,17 @@ files:
22
36
  - lib/literal/array.rb
23
37
  - lib/literal/data.rb
24
38
  - lib/literal/data_structure.rb
25
- - lib/literal/deferred_type.rb
39
+ - lib/literal/delegator.rb
26
40
  - lib/literal/enum.rb
27
41
  - lib/literal/errors/argument_error.rb
28
42
  - lib/literal/errors/error.rb
29
43
  - lib/literal/errors/type_error.rb
30
44
  - lib/literal/failure.rb
31
45
  - lib/literal/flags.rb
46
+ - lib/literal/flags/flags_16.rb
47
+ - lib/literal/flags/flags_32.rb
48
+ - lib/literal/flags/flags_64.rb
49
+ - lib/literal/flags/flags_8.rb
32
50
  - lib/literal/hash.rb
33
51
  - lib/literal/null.rb
34
52
  - lib/literal/object.rb
@@ -55,6 +73,7 @@ files:
55
73
  - lib/literal/types/boolean_type.rb
56
74
  - lib/literal/types/class_type.rb
57
75
  - lib/literal/types/constraint_type.rb
76
+ - lib/literal/types/deferred_type.rb
58
77
  - lib/literal/types/descendant_type.rb
59
78
  - lib/literal/types/enumerable_type.rb
60
79
  - lib/literal/types/falsy_type.rb
@@ -67,12 +86,14 @@ files:
67
86
  - lib/literal/types/never_type.rb
68
87
  - lib/literal/types/nilable_type.rb
69
88
  - lib/literal/types/not_type.rb
89
+ - lib/literal/types/predicate_type.rb
70
90
  - lib/literal/types/range_type.rb
71
91
  - lib/literal/types/set_type.rb
72
92
  - lib/literal/types/truthy_type.rb
73
93
  - lib/literal/types/tuple_type.rb
74
94
  - lib/literal/types/union_type.rb
75
95
  - lib/literal/types/void_type.rb
96
+ - lib/literal/value.rb
76
97
  - lib/literal/version.rb
77
98
  homepage: https://literal.fun
78
99
  licenses:
@@ -97,7 +118,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
97
118
  - !ruby/object:Gem::Version
98
119
  version: '0'
99
120
  requirements: []
100
- rubygems_version: 3.6.2
121
+ rubygems_version: 3.6.7
101
122
  specification_version: 4
102
123
  summary: Enums, properties, generics, structured objects and runtime type checking.
103
124
  test_files: []