What we need to do IO in Julia with guaranteed memory safety

Would a pointer-esque api be ok if it were memory-safe? Something like:

struct SafePointer{T}
  base::Ptr{Void} # start of the region
  len::UInt64 # length of the region
  offset::UInt64 # offset to the T

  function SafePointer{T}(base::Ptr{Void}, len::UInt64, offset::UInt64}
    @assert 0 <= offset <= len - sizeof(T)
    new(base, len, offset)
  end
end

function +(sp::SafePointer{T}, i::UInt64) where {T}
  SafePointer(sp.base, sp.len, offset+i)
end

We use something similar for implementing disk-backed betrees. It handles most of the pointer arithmetic and does bounds checks:

julia> struct Foo
       x::Int64
       y::PagedVector{Float32}
       end

julia> paged = Paged{Foo}(p)
Pageds.Paged{Foo}(Ptr{Void} @0x00000000032d9fe0)

julia> @v paged.y
3-element Pageds.PagedVector{Float32}:
 0.0
 0.0
 0.0

julia> @v paged.y[2] 
0.0f0

julia> @v paged.y[4]
ERROR: BoundsError: attempt to access 3-element Pageds.PagedVector{Float32} at index [4]

julia> y2 = @a paged.y[2] # internal pointer
Pageds.Paged{Float32}(Ptr{Void} @0x00000000032d9ffc)

julia> @v y2
0.0f0

julia> @v y2 = 7
Ptr{Float32} @0x00000000032d9ffc

julia> @v paged.y
3-element Pageds.PagedVector{Float32}:
 0.0
 7.0
 0.0

It all boils down to pointer operations which optimize really well:

julia> f(paged, x) = @v paged.y[2] = x

julia> @code_lowered f(paged, 3)
CodeInfo(:(begin 
        nothing
        return (Pageds.unsafe_store!)((Pageds.get_address)((Pageds.get_address)(paged, Val{:y}), 2), x)
    end))

julia> @code_warntype f(paged, 3)
Variables:
  #self# <optimized out>
  paged::Pageds.Paged{Foo}
  x::Int64

Body:
  begin 
      $(Expr(:inbounds, false))
      # meta: location /home/jamie/raicode/src/Pageds/Pageds.jl get_address 95
      # meta: location /home/jamie/raicode/src/Pageds/Pageds.jl # line 99:
      # meta: location /home/jamie/raicode/src/Pageds/Pageds.jl Type 18
      goto 7
      7: 
      # meta: pop location
      SSAValue(0) = $(Expr(:new, Pageds.Paged{Pageds.PagedVector{Float32}}, :((Base.bitcast)(Ptr{Void}, (Base.add_int)((Base.bitcast)(UInt64, (Core.getfield)(paged, :ptr)::Ptr{Void}), 0x0000000000000008)::UInt64))))
      # meta: pop location
      # meta: pop location
      $(Expr(:inbounds, :pop))
      SSAValue(1) = $(Expr(:invoke, MethodInstance for get_address(::Pageds.Paged{Pageds.PagedVector{Float32}}, ::Int64), :(Pageds.get_address), SSAValue(0), 2))
      $(Expr(:inbounds, false))
      # meta: location /home/jamie/raicode/src/Pageds/Pageds.jl unsafe_store! 142
      # meta: location /home/jamie/raicode/src/Pageds/Pageds.jl unsafe_store! 122
      # meta: location /home/jamie/raicode/src/Pageds/Pageds.jl # line 126:
      SSAValue(2) = (Base.pointerset)((Base.bitcast)(Ptr{Float32}, (Core.getfield)(SSAValue(1), :ptr)::Ptr{Void}), (Base.sitofp)(Float32, x::Int64)::Float32, 1, 1)::Ptr{Float32}
      # meta: pop location
      # meta: pop location
      # meta: pop location
      $(Expr(:inbounds, :pop))
      return SSAValue(2)
  end::Ptr{Float32}

julia> @code_native f(paged, 3)
	.text
Filename: REPL[27]
	pushq	%rbp
	movq	%rsp, %rbp
	pushq	%rbx
	pushq	%rax
	movq	%rsi, %rbx
Source line: 99
	movq	(%rdi), %rax
	addq	$8, %rax
	movq	%rax, -16(%rbp)
Source line: 1
	movabsq	$get_address, %rax
	leaq	-16(%rbp), %rdi
	movl	$2, %esi
	callq	*%rax
Source line: 126
	xorps	%xmm0, %xmm0
	cvtsi2ssq	%rbx, %xmm0
	movss	%xmm0, (%rax)
Source line: 1
	addq	$8, %rsp
	popq	%rbx
	popq	%rbp
	retq
	nopl	(%rax)