[swift-users] raw buffer pointer load alignment

Johannes Weiß johannesweiss at apple.com
Wed Nov 8 19:49:10 CST 2017


Hi Kelvin,

> On 8 Nov 2017, at 5:40 pm, Kelvin Ma <kelvin13ma at gmail.com> wrote:
> 
> yikes there’s no less verbose way to do that? and if the type isn’t an integer there’s no way to avoid the default initialization? Can this be done with opaques or something?

well, it's 5 lines for the generic case to rule all the integers. You could just put that in a function and never think about it again, right?

func integerFromBuffer<T: FixedWidthInteger>(_ pointer: UnsafeRawBufferPointer, index: Int) -> T {
    precondition(index >= 0)
    precondition(index <= pointer.count - MemoryLayout<T>.size)

    var value = T()
    withUnsafeMutableBytes(of: &value) { valuePtr in
        valuePtr.copyBytes(from: UnsafeRawBufferPointer(start: pointer.baseAddress!.advanced(by: index),
                                                        count: MemoryLayout<T>.size))
    }
    return value
}

should work (untested). Also you might need to handle endianness.

Regarding types that are not integers, what types are you thinking of? For normal Swift types the layout isn't guaranteed so you can't just read the bytes from somewhere. For C types where the layout is known you can just use the above code and either relax the constraint or specialise it to the very type you need. The only requirement of the type (besides that it's layout is defined) is that is has an empty constructor.

-- Johannes

> On Wed, Nov 8, 2017 at 7:04 PM, Johannes Weiß <johannesweiss at apple.com> wrote:
> Hi Kelvin,
> 
> > On 8 Nov 2017, at 4:54 pm, Kelvin Ma via swift-users <swift-users at swift.org> wrote:
> >
> > According to the docs, the load(fromByteOffset:as:) method requires the instance to be “properly aligned” Does that mean if I have raw data meant to be interpreted as
> >
> > 0      1      2      3      4      5      6
> > [ Int8 |    Int16    |    Int16    | Int8 | Int8 ]
> >
> >
> > i can’t just load the Int16 from byte offset 1?
> 
> you can't just dereference that pointer as an Int16 (in any language) without causing UB but it's not really an issue, just do this (assuming `ptr` is the pointer into your data and `index` is the index to where your Int16 lives):
> 
> 
>     var value: Int16 = 0
>     withUnsafeMutableBytes(of: &value) { valuePtr in
>         valuePtr.copyBytes(from: UnsafeRawBufferPointer(start: ptr.baseAddress!.advanced(by: index),
>                                                         count: MemoryLayout<Int16>.size))
>     }
> 
> you can have the whole thing generic too for <T: FixedWidthInteger>
> 
>     var value: T = 0
>     withUnsafeMutableBytes(of: &value) { valuePtr in
>         valuePtr.copyBytes(from: UnsafeRawBufferPointer(start: ptr.baseAddress!.advanced(by: index),
>                                                         count: MemoryLayout<T>.size))
>     }
> 
> -- Johannes
> 
> 
> > _______________________________________________
> > swift-users mailing list
> > swift-users at swift.org
> > https://lists.swift.org/mailman/listinfo/swift-users
> 
> 



More information about the swift-users mailing list