%a{annotate:rdoc:skip}
module ObjectSpace
  # <!-- rdoc-file=weakmap.c -->
  # An ObjectSpace::WeakKeyMap object holds references to any objects, but objects
  # uses as keys can be garbage collected.
  #
  # Objects used as values can't be garbage collected until the key is.
  #
  class WeakKeyMap[Key, Value]
    public

    # <!--
    #   rdoc-file=weakmap.c
    #   - map[key] -> value
    # -->
    # Returns the value associated with the given `key` if found.
    #
    # If `key` is not found, returns `nil`.
    #
    def []: (Key) -> Value?

    # <!--
    #   rdoc-file=weakmap.c
    #   - map[key] = value -> value
    # -->
    # Associates the given `value` with the given `key`; returns `value`.
    #
    # The reference to `key` is weak, so when there is no other reference to `key`
    # it may be garbage collected.
    #
    # If the given `key` exists, replaces its value with the given `value`; the
    # ordering is not affected
    #
    def []=: (Key, Value?) -> Value?

    # <!--
    #   rdoc-file=weakmap.c
    #   - map.clear -> self
    # -->
    # Removes all map entries; returns `self`.
    #
    def clear: () -> self

    # <!--
    #   rdoc-file=weakmap.c
    #   - map.delete(key) -> value or nil
    #   - map.delete(key) {|key| ... } -> object
    # -->
    # Deletes the entry for the given `key` and returns its associated value.
    #
    # If no block is given and `key` is found, deletes the entry and returns the
    # associated value:
    #     m = ObjectSpace::WeakKeyMap.new
    #     m["foo"] = 1
    #     m.delete("foo") # => 1
    #     m["foo"] # => nil
    #
    # If no block given and `key` is not found, returns `nil`.
    #
    # If a block is given and `key` is found, ignores the block, deletes the entry,
    # and returns the associated value:
    #     m = ObjectSpace::WeakKeyMap.new
    #     m["foo"] = 2
    #     h.delete("foo") { |key| raise 'Will never happen'} # => 2
    #
    # If a block is given and `key` is not found, calls the block and returns the
    # block's return value:
    #     m = ObjectSpace::WeakKeyMap.new
    #     h.delete("nosuch") { |key| "Key #{key} not found" } # => "Key nosuch not found"
    #
    def delete: (Key) -> Value?
              | [T] (Key) { (Key) -> T } -> (Value | T)

    # <!--
    #   rdoc-file=weakmap.c
    #   - map.getkey(key) -> existing_key or nil
    # -->
    # Returns the existing equal key if it exists, otherwise returns `nil`.
    #
    def getkey: (untyped) -> Key?

    # <!--
    #   rdoc-file=weakmap.c
    #   - map.inspect -> new_string
    # -->
    # Returns a new String containing informations about the map:
    #
    #     m = ObjectSpace::WeakKeyMap.new
    #     m[key] = value
    #     m.inspect # => "#<ObjectSpace::WeakKeyMap:0x00000001028dcba8 size=1>"
    #
    def inspect: () -> String

    # <!--
    #   rdoc-file=weakmap.c
    #   - hash.key?(key) -> true or false
    # -->
    # Returns `true` if `key` is a key in `self`, otherwise `false`.
    #
    def key?: (Key) -> bool
  end
end
