2021-01-09 23:51:37 +00:00
|
|
|
module Spectator
|
|
|
|
# Typeless wrapper for a value.
|
|
|
|
# Stores any value or reference type.
|
|
|
|
# However, the type must be known when retrieving the value.
|
2021-02-10 05:50:09 +00:00
|
|
|
#
|
|
|
|
# This type is expected to be used like so:
|
|
|
|
# ```
|
|
|
|
# wrapper = Wrapper.new("wrapped")
|
|
|
|
# value = wrapper.get(String)
|
|
|
|
# ```
|
2021-01-09 23:51:37 +00:00
|
|
|
struct Wrapper
|
2022-03-20 04:48:55 +00:00
|
|
|
@pointer : Void*
|
2021-01-09 23:51:37 +00:00
|
|
|
|
|
|
|
# Creates a wrapper for the specified value.
|
|
|
|
def initialize(value)
|
2023-03-28 00:37:50 +00:00
|
|
|
@pointer = Value.new(value).as(Void*)
|
2021-01-09 23:51:37 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
# Retrieves the previously wrapped value.
|
|
|
|
# The *type* of the wrapped value must match otherwise an error will be raised.
|
|
|
|
def get(type : T.class) : T forall T
|
2023-03-28 00:37:50 +00:00
|
|
|
@pointer.unsafe_as(Value(T)).get
|
2021-01-09 23:51:37 +00:00
|
|
|
end
|
|
|
|
|
2021-01-31 06:49:20 +00:00
|
|
|
# Retrieves the previously wrapped value.
|
|
|
|
# Alternate form of `#get` that accepts a block.
|
|
|
|
# The block must return the same type as the wrapped value, otherwise an error will be raised.
|
|
|
|
# This method gets around the issue where the value might be a type (i.e. `Int32.class`).
|
|
|
|
# The block will never be executed, it is only used for type information.
|
2021-02-10 05:50:09 +00:00
|
|
|
#
|
|
|
|
# ```
|
|
|
|
# wrapper = Wrapper.new(Int32)
|
|
|
|
# # type = wrapper.get(Int32.class) # Does not work!
|
|
|
|
# type = wrapper.get { Int32 } # Returns Int32
|
|
|
|
# ```
|
2021-01-31 06:49:20 +00:00
|
|
|
def get(& : -> T) : T forall T
|
2023-03-28 00:37:50 +00:00
|
|
|
@pointer.unsafe_as(Value(T)).get
|
|
|
|
end
|
|
|
|
|
|
|
|
# Wrapper for a value.
|
|
|
|
# Similar to `Box`, but doesn't segfault on nil and unions.
|
|
|
|
private class Value(T)
|
|
|
|
# Creates the wrapper.
|
|
|
|
def initialize(@value : T)
|
|
|
|
end
|
|
|
|
|
|
|
|
# Retrieves the value.
|
|
|
|
def get : T
|
|
|
|
@value
|
|
|
|
end
|
2021-01-09 23:51:37 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|