Class: Rigor::Type::HashShape
- Inherits:
-
Object
- Object
- Rigor::Type::HashShape
- Defined in:
- lib/rigor/type/hash_shape.rb
Overview
A hash shape with statically known keys. Inhabitants are Ruby ‘Hash` instances whose known entries inhabit the corresponding value types. RBS records correspond to the exact closed subset; Rigor extends that carrier with optional keys, read-only entry views, and an open/closed extra-key policy.
Keys are restricted to Symbol and String values. Exact closed symbol-keyed shapes erase to the RBS record syntax ‘{ a: Integer, ?b: String }`; all other shapes degrade to `Hash[K, V]` or raw `Hash` when no useful bounds are available.
Equality and hashing are structural over the (key -> Rigor::Type) pair set and policy fields. Hash insertion order is preserved by the underlying storage but does NOT affect equality (matching Ruby’s ‘Hash#==`).
See docs/type-specification/rbs-compatible-types.md (records) and docs/type-specification/rigor-extensions.md (hash shape). rubocop:disable Metrics/ClassLength
Constant Summary collapse
- ALLOWED_KEY_CLASSES =
[Symbol, String].freeze
- EXTRA_KEY_POLICIES =
%i[open closed].freeze
- POLICY_KEYWORDS =
%i[required_keys optional_keys read_only_keys extra_keys].freeze
Instance Attribute Summary collapse
-
#extra_keys ⇒ Object
readonly
Returns the value of attribute extra_keys.
-
#optional_keys ⇒ Object
readonly
Returns the value of attribute optional_keys.
-
#pairs ⇒ Object
readonly
Returns the value of attribute pairs.
-
#read_only_keys ⇒ Object
readonly
Returns the value of attribute read_only_keys.
-
#required_keys ⇒ Object
readonly
Returns the value of attribute required_keys.
Instance Method Summary collapse
- #==(other) ⇒ Object (also: #eql?)
- #accepts(other, mode: :gradual) ⇒ Object
- #bot ⇒ Object
- #closed? ⇒ Boolean
- #describe(verbosity = :short) ⇒ Object
- #dynamic ⇒ Object
-
#erase_to_rbs ⇒ Object
Erases to the RBS record form ‘{ a: Integer, ?b: String }` for exact closed symbol-keyed shapes.
- #hash ⇒ Object
-
#initialize(pairs = nil, **keywords) ⇒ HashShape
constructor
A new instance of HashShape.
- #inspect ⇒ Object
- #open? ⇒ Boolean
- #optional_key?(key) ⇒ Boolean
- #read_only_key?(key) ⇒ Boolean
- #required_key?(key) ⇒ Boolean
- #top ⇒ Object
Constructor Details
#initialize(pairs = nil, **keywords) ⇒ HashShape
Returns a new instance of HashShape.
49 50 51 52 53 54 55 56 |
# File 'lib/rigor/type/hash_shape.rb', line 49 def initialize(pairs = nil, **keywords) pairs, policy = split_constructor_args(pairs, keywords) validate_pairs!(pairs) @pairs = pairs.dup.freeze apply_policy!(policy) freeze end |
Instance Attribute Details
#extra_keys ⇒ Object (readonly)
Returns the value of attribute extra_keys.
31 32 33 |
# File 'lib/rigor/type/hash_shape.rb', line 31 def extra_keys @extra_keys end |
#optional_keys ⇒ Object (readonly)
Returns the value of attribute optional_keys.
31 32 33 |
# File 'lib/rigor/type/hash_shape.rb', line 31 def optional_keys @optional_keys end |
#pairs ⇒ Object (readonly)
Returns the value of attribute pairs.
31 32 33 |
# File 'lib/rigor/type/hash_shape.rb', line 31 def pairs @pairs end |
#read_only_keys ⇒ Object (readonly)
Returns the value of attribute read_only_keys.
31 32 33 |
# File 'lib/rigor/type/hash_shape.rb', line 31 def read_only_keys @read_only_keys end |
#required_keys ⇒ Object (readonly)
Returns the value of attribute required_keys.
31 32 33 |
# File 'lib/rigor/type/hash_shape.rb', line 31 def required_keys @required_keys end |
Instance Method Details
#==(other) ⇒ Object Also known as: eql?
114 115 116 117 118 119 120 121 |
# File 'lib/rigor/type/hash_shape.rb', line 114 def ==(other) other.is_a?(HashShape) && pairs == other.pairs && required_keys == other.required_keys && optional_keys == other.optional_keys && read_only_keys == other.read_only_keys && extra_keys == other.extra_keys end |
#accepts(other, mode: :gradual) ⇒ Object
110 111 112 |
# File 'lib/rigor/type/hash_shape.rb', line 110 def accepts(other, mode: :gradual) Inference::Acceptance.accepts(self, other, mode: mode) end |
#closed? ⇒ Boolean
82 83 84 |
# File 'lib/rigor/type/hash_shape.rb', line 82 def closed? extra_keys == :closed end |
#describe(verbosity = :short) ⇒ Object
58 59 60 61 62 63 64 |
# File 'lib/rigor/type/hash_shape.rb', line 58 def describe(verbosity = :short) return "{}" if pairs.empty? rendered = pairs.map { |k, v| render_entry(k, v, verbosity) } rendered << "..." if open? "{ #{rendered.join(', ')} }" end |
#dynamic ⇒ Object
106 107 108 |
# File 'lib/rigor/type/hash_shape.rb', line 106 def dynamic Trinary.no end |
#erase_to_rbs ⇒ Object
Erases to the RBS record form ‘{ a: Integer, ?b: String }` for exact closed symbol-keyed shapes. Open shapes and string-keyed closed shapes degrade to a generic Hash bound.
69 70 71 72 73 74 75 76 |
# File 'lib/rigor/type/hash_shape.rb', line 69 def erase_to_rbs return "{}" if pairs.empty? && closed? return hash_erasure unless closed? return hash_erasure if pairs.each_key.any? { |k| !k.is_a?(Symbol) } rendered = pairs.map { |k, v| "#{record_key(k)}: #{v.erase_to_rbs}" } "{ #{rendered.join(', ')} }" end |
#hash ⇒ Object
124 125 126 |
# File 'lib/rigor/type/hash_shape.rb', line 124 def hash [HashShape, pairs, required_keys, optional_keys, read_only_keys, extra_keys].hash end |
#inspect ⇒ Object
128 129 130 |
# File 'lib/rigor/type/hash_shape.rb', line 128 def inspect "#<Rigor::Type::HashShape #{describe(:short)}>" end |
#open? ⇒ Boolean
78 79 80 |
# File 'lib/rigor/type/hash_shape.rb', line 78 def open? extra_keys == :open end |
#optional_key?(key) ⇒ Boolean
90 91 92 |
# File 'lib/rigor/type/hash_shape.rb', line 90 def optional_key?(key) optional_keys.include?(key) end |
#read_only_key?(key) ⇒ Boolean
94 95 96 |
# File 'lib/rigor/type/hash_shape.rb', line 94 def read_only_key?(key) read_only_keys.include?(key) end |
#required_key?(key) ⇒ Boolean
86 87 88 |
# File 'lib/rigor/type/hash_shape.rb', line 86 def required_key?(key) required_keys.include?(key) end |