Interpreting raw memory as a vector of unions

To avoid excessive allocation & garbage collection for performance critical applications, I sometimes use the following approach (simplified):

buffer = pointer(Vector{UInt8}(undef, 100))
function alloc(::Type{T}, n, offset) where T
    size = n * sizeof(T)
    ptr = buffer + offset
    unsafe_wrap(Vector{T}, convert(Ptr{T}, ptr), n), offset + size
end

julia> offset = 0
0

julia> a, offset = alloc(Int, 2, offset)
([4627565936, 4627565936], 16)

julia> a, offset = alloc(Float64, 2, offset)
([2.2864006326e-314, 2.394940531e-314], 32)

This works for any isbits type. Is it possible directly interpret a chunk of memory as a vector of isbitsunion elements, .e.g. Union{Nothing, Int64}? I couldn’t find anything in docs and unsafe_wrap doesn’t work either:

julia> a = unsafe_wrap(Vector{Int64}, pointer([1,2,3]), 3)
3-element Vector{Int64}:
 1
 2
 3

julia> a = unsafe_wrap(Vector{Union{Nothing, Int64}}, pointer([1,2,nothing]), 3)
ERROR: ArgumentError: unsafe_wrap: unspecified layout for union element type
Stacktrace:
 [1] #unsafe_wrap#81
   @ ./pointer.jl:89 [inlined]
 [2] unsafe_wrap(::Type{Vector{Union{Nothing, Int64}}}, p::Ptr{Union{Nothing, Int64}}, d::Int64)
   @ Base ./pointer.jl:89
 [3] top-level scope
   @ REPL[76]:1

@Sheemon7 - did you ever find a solution to this problem? Thanks.

No, unfortunately not :frowning:

How should this work? What value would indicate the position has nothing and how it would not be a valid Int64 value?

Union{Nothing, Int64} is not isbitstype but it is isbitsunion. Thanks to the isbits union optimizations this type can be stored inline in an array. It can’t quite be unsafe_wrap’d as desired due to the extra “type tag array” but it can still pretty much work:

julia> buffer = resize!(Vector{Union{Nothing, Int64}}(), 100)
 nothing
 ...

julia> function alloc(::Type{Union{Nothing,Int64}}, n, offset)
           view(buffer, UnitRange(offset, offset + n - 1)), offset + n
       end
alloc (generic function with 1 method)

julia> alloc(Union{Nothing,Int64}, 2, 1)
(Union{Nothing, Int64}[nothing, nothing], 3)