appending packed bytes to [UInt8]

I want to create a buffer with the layout

0 4 8 12 13 14 15 16
[ x:Float | y:Float | z:Float | r:UInt8 | g:UInt8 | b:UInt8 |
_:UInt8 ]

Normally, I’d use UnsafeRawBufferPointer for this, but I need the buffer to
be a vector (i.e. with append(_:)), and for it to return a Swift-managed
Array<UInt8>. How should I do this? The project does not use Foundation.

I'm not sure what you mean by "I need the buffer to be a vector /.../" but
perhaps this may be of some help:

struct S {
    var x: Float
    var y: Float
    var z: Float
    var r: UInt8
    var g: UInt8
    var b: UInt8
    var a: UInt8
}
var buf = S(x: 0.1, y: 1.2, z: 2.3, r: 11, g: 22, b: 33, a: 44)
print(MemoryLayout<S>.stride) // 16
withUnsafeMutableBytes(of: &buf) { ptr in
    print("x:", ptr.load(fromByteOffset: 0, as: Float.self)) // 0.1
    print("y:", ptr.load(fromByteOffset: 4, as: Float.self)) // 1.2
    print("z:", ptr.load(fromByteOffset: 8, as: Float.self)) // 2.3
    print("r:", ptr.load(fromByteOffset: 12, as: UInt8.self)) // 11
    print("g:", ptr.load(fromByteOffset: 13, as: UInt8.self)) // 22
    print("b:", ptr.load(fromByteOffset: 14, as: UInt8.self)) // 33
    print("a:", ptr.load(fromByteOffset: 15, as: UInt8.self)) // 44
}

NOTE however that the memory layout of Swift-structs is not guaranteed to
remain like this and is thus not future-proof, although I think that
if/when things changes, there will be some way to tell the compiler that
you want the memory to be this "expected" "C-like" layout.

/Jens

···

On Wed, Jan 10, 2018 at 10:03 PM, Kelvin Ma via swift-users < swift-users@swift.org> wrote:

I want to create a buffer with the layout

0 4 8 12 13 14 15 16
[ x:Float | y:Float | z:Float | r:UInt8 | g:UInt8 | b:UInt8 |
_:UInt8 ]

Normally, I’d use UnsafeRawBufferPointer for this, but I need the buffer
to be a vector (i.e. with append(_:)), and for it to return a
Swift-managed Array<UInt8>. How should I do this? The project does not
use Foundation.

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

Conversely, since I’m pretty sure the memory layout of a *tuple* is
guaranteed to be as it appears, I would probably start with something like
this:

typealias Vec3rgba = (x: Float, y: Float, z: Float, r: Int8, g: Int8, b:
Int8, a: Int8)

Nevin

···

On Wed, Jan 10, 2018 at 4:27 PM, Jens Persson via swift-users < swift-users@swift.org> wrote:

I'm not sure what you mean by "I need the buffer to be a vector /.../" but
perhaps this may be of some help:

struct S {
    var x: Float
    var y: Float
    var z: Float
    var r: UInt8
    var g: UInt8
    var b: UInt8
    var a: UInt8
}
var buf = S(x: 0.1, y: 1.2, z: 2.3, r: 11, g: 22, b: 33, a: 44)
print(MemoryLayout<S>.stride) // 16
withUnsafeMutableBytes(of: &buf) { ptr in
    print("x:", ptr.load(fromByteOffset: 0, as: Float.self)) // 0.1
    print("y:", ptr.load(fromByteOffset: 4, as: Float.self)) // 1.2
    print("z:", ptr.load(fromByteOffset: 8, as: Float.self)) // 2.3
    print("r:", ptr.load(fromByteOffset: 12, as: UInt8.self)) // 11
    print("g:", ptr.load(fromByteOffset: 13, as: UInt8.self)) // 22
    print("b:", ptr.load(fromByteOffset: 14, as: UInt8.self)) // 33
    print("a:", ptr.load(fromByteOffset: 15, as: UInt8.self)) // 44
}

NOTE however that the memory layout of Swift-structs is not guaranteed to
remain like this and is thus not future-proof, although I think that
if/when things changes, there will be some way to tell the compiler that
you want the memory to be this "expected" "C-like" layout.

/Jens

On Wed, Jan 10, 2018 at 10:03 PM, Kelvin Ma via swift-users < > swift-users@swift.org> wrote:

I want to create a buffer with the layout

0 4 8 12 13 14 15 16
[ x:Float | y:Float | z:Float | r:UInt8 | g:UInt8 | b:UInt8
> _:UInt8 ]

Normally, I’d use UnsafeRawBufferPointer for this, but I need the buffer
to be a vector (i.e. with append(_:)), and for it to return a
Swift-managed Array<UInt8>. How should I do this? The project does not
use Foundation.

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

I’ve asked similar questions in the past and everyone said this is not
valid Swift, not the least because the compiler can pad structs and
rearrange its layout. For example if there were only 3 UInt8s, the stride
should be 15, not 16 as they need to be packed densely. since they are
misaligned you also can’t use load and store (they will trap)

···

On Wed, Jan 10, 2018 at 4:27 PM, Jens Persson <jens@bitcycle.com> wrote:

I'm not sure what you mean by "I need the buffer to be a vector /.../" but
perhaps this may be of some help:

struct S {
    var x: Float
    var y: Float
    var z: Float
    var r: UInt8
    var g: UInt8
    var b: UInt8
    var a: UInt8
}
var buf = S(x: 0.1, y: 1.2, z: 2.3, r: 11, g: 22, b: 33, a: 44)
print(MemoryLayout<S>.stride) // 16
withUnsafeMutableBytes(of: &buf) { ptr in
    print("x:", ptr.load(fromByteOffset: 0, as: Float.self)) // 0.1
    print("y:", ptr.load(fromByteOffset: 4, as: Float.self)) // 1.2
    print("z:", ptr.load(fromByteOffset: 8, as: Float.self)) // 2.3
    print("r:", ptr.load(fromByteOffset: 12, as: UInt8.self)) // 11
    print("g:", ptr.load(fromByteOffset: 13, as: UInt8.self)) // 22
    print("b:", ptr.load(fromByteOffset: 14, as: UInt8.self)) // 33
    print("a:", ptr.load(fromByteOffset: 15, as: UInt8.self)) // 44
}

NOTE however that the memory layout of Swift-structs is not guaranteed to
remain like this and is thus not future-proof, although I think that
if/when things changes, there will be some way to tell the compiler that
you want the memory to be this "expected" "C-like" layout.

/Jens

On Wed, Jan 10, 2018 at 10:03 PM, Kelvin Ma via swift-users < > swift-users@swift.org> wrote:

I want to create a buffer with the layout

0 4 8 12 13 14 15 16
[ x:Float | y:Float | z:Float | r:UInt8 | g:UInt8 | b:UInt8
> _:UInt8 ]

Normally, I’d use UnsafeRawBufferPointer for this, but I need the buffer
to be a vector (i.e. with append(_:)), and for it to return a
Swift-managed Array<UInt8>. How should I do this? The project does not
use Foundation.

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

I thought tuples, like structs do *not* have fixed layout. And they get
padded too.

···

On Wed, Jan 10, 2018 at 5:01 PM, Nevin Brackett-Rozinsky < nevin.brackettrozinsky@gmail.com> wrote:

Conversely, since I’m pretty sure the memory layout of a *tuple* is
guaranteed to be as it appears, I would probably start with something like
this:

typealias Vec3rgba = (x: Float, y: Float, z: Float, r: Int8, g: Int8, b:
Int8, a: Int8)

Nevin

On Wed, Jan 10, 2018 at 4:27 PM, Jens Persson via swift-users < > swift-users@swift.org> wrote:

I'm not sure what you mean by "I need the buffer to be a vector /.../"
but perhaps this may be of some help:

struct S {
    var x: Float
    var y: Float
    var z: Float
    var r: UInt8
    var g: UInt8
    var b: UInt8
    var a: UInt8
}
var buf = S(x: 0.1, y: 1.2, z: 2.3, r: 11, g: 22, b: 33, a: 44)
print(MemoryLayout<S>.stride) // 16
withUnsafeMutableBytes(of: &buf) { ptr in
    print("x:", ptr.load(fromByteOffset: 0, as: Float.self)) // 0.1
    print("y:", ptr.load(fromByteOffset: 4, as: Float.self)) // 1.2
    print("z:", ptr.load(fromByteOffset: 8, as: Float.self)) // 2.3
    print("r:", ptr.load(fromByteOffset: 12, as: UInt8.self)) // 11
    print("g:", ptr.load(fromByteOffset: 13, as: UInt8.self)) // 22
    print("b:", ptr.load(fromByteOffset: 14, as: UInt8.self)) // 33
    print("a:", ptr.load(fromByteOffset: 15, as: UInt8.self)) // 44
}

NOTE however that the memory layout of Swift-structs is not guaranteed to
remain like this and is thus not future-proof, although I think that
if/when things changes, there will be some way to tell the compiler that
you want the memory to be this "expected" "C-like" layout.

/Jens

On Wed, Jan 10, 2018 at 10:03 PM, Kelvin Ma via swift-users < >> swift-users@swift.org> wrote:

I want to create a buffer with the layout

0 4 8 12 13 14 15 16
[ x:Float | y:Float | z:Float | r:UInt8 | g:UInt8 | b:UInt8
> _:UInt8 ]

Normally, I’d use UnsafeRawBufferPointer for this, but I need the
buffer to be a vector (i.e. with append(_:)), and for it to return a
Swift-managed Array<UInt8>. How should I do this? The project does not
use Foundation.

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users