# Move bytes to extern struct

**URL:** <https://ziggit.dev/t/move-bytes-to-extern-struct/6443>\
**Category:** Help\
**Tags:** memory-management\
**Created:** [October 20, 2024, 10:43am UTC](https://ziggit.dev/t/move-bytes-to-extern-struct/6443 "2024-10-20T10:43:03Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![ericlang](https://ziggit.dev/user_avatar/ziggit.dev/ericlang/32/8515_2.png) [@ericlang](https://ziggit.dev/u/ericlang)\
**Post date:** [October 20, 2024, 10:43am UTC](https://ziggit.dev/t/move-bytes-to-extern-struct/6443/1 "2024-10-20T10:43:03Z")

</div>

I have an `extern struct` of exactly x bytes.  
I read a file into a slice of bytes ([]u8).  
How can I move x bytes into that struct?  
This saves time reading / manipulating the separate fields.

---

<div class="post-metadata">

**Author:** ![dee0xeed](https://ziggit.dev/letter_avatar_proxy/v4/letter/d/3ab097/32.png) [@dee0xeed](https://ziggit.dev/u/dee0xeed)\
**Post date:** [October 20, 2024, 12:16pm UTC](https://ziggit.dev/t/move-bytes-to-extern-struct/6443/2 "2024-10-20T12:16:09Z")

</div>

You can just reinterpret memory without physical move:

```zig
const std = @import("std");
const S = extern struct {
    a: u8,
    b: u32 align(1),
};

pub fn main() void {
    const d: [5]u8 = .{0x07, 0x01, 0x02, 0x03, 0x04};
    const p: *const S = @ptrCast(&d);
    std.debug.print("{}\n", .{@sizeOf(S)});
    std.debug.print("{any}\n", .{p.*});
    // 0x04030201 = 67305985
}

```

---

<div class="post-metadata">

**Author:** ![ericlang](https://ziggit.dev/user_avatar/ziggit.dev/ericlang/32/8515_2.png) [@ericlang](https://ziggit.dev/u/ericlang)\
**Post date:** [October 20, 2024, 12:46pm UTC](https://ziggit.dev/t/move-bytes-to-extern-struct/6443/3 "2024-10-20T12:46:42Z")

</div>

Ok that is a nice one to know.  
But after reading the bytes two fields have to be swapped, so i would rather copy the bytes first.

```zig
pub const SectionHeader = extern struct
{
    pub const STRUCTSIZE: u16 = @sizeOf(SectionHeader); // this must be 10.

    bitcount: u8 = 0,
    checksum: u8 = 0,
    _unused1: u16 = 0,
    decompressed_size: u16 = 0, // big endian on disk
    _unused2: u16 = 0,  
    compressed_size: u16 = 0, // big endian on disk

    pub fn init_from_bytes(bytes: []u8, offset: usize) SectionHeader
    {
        // Here i want to move 10 bytes from bytes[offset..offset + 10] into the struct.
        // After that i need to correct the 2 big endian fields.
    }
}

```

---

<div class="post-metadata">

**Author:** ![dee0xeed](https://ziggit.dev/letter_avatar_proxy/v4/letter/d/3ab097/32.png) [@dee0xeed](https://ziggit.dev/u/dee0xeed)\
**Post date:** [October 20, 2024, 1:01pm UTC](https://ziggit.dev/t/move-bytes-to-extern-struct/6443/4 "2024-10-20T13:01:30Z")

</div>

> [@ericlang](#):
>
> But after reading the bytes two fields have to be swapped

You can swap them in place:

```zig
const std = @import("std");
const S = extern struct {
    a: u8,
    b: u16 align(1), // BE
};

fn swapBytes(d: *align(1) u16) void{
    _ = d;
    //...
}

pub fn main() void {
    var d: [3]u8 = .{0x07, 0x00, 0x01};
                          // BE here
    const p: *S = @ptrCast(&d);
    std.debug.print("{}\n", .{@sizeOf(S)});
    swapBytes(&p.b);
    std.debug.print("{any}\n", .{p.*});
}

```

---

<div class="post-metadata">

**Author:** ![dee0xeed](https://ziggit.dev/letter_avatar_proxy/v4/letter/d/3ab097/32.png) [@dee0xeed](https://ziggit.dev/u/dee0xeed)\
**Post date:** [October 20, 2024, 1:19pm UTC](https://ziggit.dev/t/move-bytes-to-extern-struct/6443/5 "2024-10-20T13:19:12Z")

</div>

> [@ericlang](#):
>
> `pub fn init_from_bytes(bytes: []u8, offset: usize) SectionHeader`

I think you can return `*SectionHeader` here.  
BTW, please, someone who knows, give a tip where stuff like C’s `htons()` is in Zig stdlib?

---

<div class="post-metadata">

**Author:** ![pierrelgol](https://ziggit.dev/user_avatar/ziggit.dev/pierrelgol/32/10233_2.png) [@pierrelgol](https://ziggit.dev/u/pierrelgol)\
**Post date:** [October 20, 2024, 1:57pm UTC](https://ziggit.dev/t/move-bytes-to-extern-struct/6443/6 "2024-10-20T13:57:35Z")

</div>

no problem it’s in `std.mem.nativeToBig` and the reverse `std.mem.bigToNative` i think it’s the name not sure but it’s there

---

<div class="post-metadata">

**Author:** ![dee0xeed](https://ziggit.dev/letter_avatar_proxy/v4/letter/d/3ab097/32.png) [@dee0xeed](https://ziggit.dev/u/dee0xeed)\
**Post date:** [October 20, 2024, 2:12pm UTC](https://ziggit.dev/t/move-bytes-to-extern-struct/6443/7 "2024-10-20T14:12:52Z")

</div>

Version 3. 🙂

```zig
const std = @import("std");
const S = extern struct {
    a: u8,
    b: u16 align(1), // supposed to be in BE byte order
    fn initFromBytes(d: []u8) *S {
        const p: *S = @ptrCast(d);
        p.b = std.mem.bigToNative(u16, p.b);
        return p;
    }
};

pub fn main() void {
    var d: [3]u8 = .{0x07, 0x00, 0x01};
                          // BE here
    const p: *S = S.initFromBytes(&d);
    std.debug.print("{}\n", .{@sizeOf(S)});
    std.debug.print("{any}\n", .{p.*});
    // { .a = 7, .b = 1 } as expected on LE machine
}

```

---

<div class="post-metadata">

**Author:** ![ericlang](https://ziggit.dev/user_avatar/ziggit.dev/ericlang/32/8515_2.png) [@ericlang](https://ziggit.dev/u/ericlang)\
**Post date:** [October 20, 2024, 3:57pm UTC](https://ziggit.dev/t/move-bytes-to-extern-struct/6443/8 "2024-10-20T15:57:56Z")

</div>

Thanks! I will play around with that.

Edit: BTW I just came from Delphi from C# from Rust and then moved to Zig, which seems promising. Ultimate control.

I made my choice with brackets and naming 🙂  
Brackets on new line: I can’t read asymmetric code.  
Everything snake\_case except types, which are PascalCase.

---

<div class="post-metadata">

**Author:** ![dee0xeed](https://ziggit.dev/letter_avatar_proxy/v4/letter/d/3ab097/32.png) [@dee0xeed](https://ziggit.dev/u/dee0xeed)\
**Post date:** [October 20, 2024, 4:55pm UTC](https://ziggit.dev/t/move-bytes-to-extern-struct/6443/9 "2024-10-20T16:55:27Z")

</div>

> [@ericlang](#):
>
> I will play around with that

See also [this topic](https://ziggit.dev/t/mapping-64-u8-buffer-to-a-struct/6052), very similar.

---

<div class="post-metadata">

**Author:** ![chung-leong](https://ziggit.dev/user_avatar/ziggit.dev/chung-leong/32/999_2.png) [@chung-leong](https://ziggit.dev/u/chung-leong)\
**Post date:** [October 20, 2024, 9:05pm UTC](https://ziggit.dev/t/move-bytes-to-extern-struct/6443/10 "2024-10-20T21:05:29Z")

</div>

You can also use [std.mem.bytesToValue()](https://ziglang.org/documentation/master/std/#std.mem.bytesToValue).

---

<div class="post-metadata">

**Author:** ![ericlang](https://ziggit.dev/user_avatar/ziggit.dev/ericlang/32/8515_2.png) [@ericlang](https://ziggit.dev/u/ericlang)\
**Post date:** [October 20, 2024, 9:46pm UTC](https://ziggit.dev/t/move-bytes-to-extern-struct/6443/11 "2024-10-20T21:46:44Z")

</div>

Wow. this bytesToValue seems perfect!  
Do we finally have a language which understands what is needed?  
In C# or Rust it is quite a hell to do this.

---

<div class="post-metadata">

**Author:** ![dee0xeed](https://ziggit.dev/letter_avatar_proxy/v4/letter/d/3ab097/32.png) [@dee0xeed](https://ziggit.dev/u/dee0xeed)\
**Post date:** [October 21, 2024, 7:06am UTC](https://ziggit.dev/t/move-bytes-to-extern-struct/6443/12 "2024-10-21T07:06:33Z")

</div>

> [@ericlang](#):
>
> Wow. this bytesToValue seems perfect!

`bytesToValue` calls `bytesAsValue` which in turn is doing what I proposed in the very beginning (pointer casting, to avoid copying):

```zig
/// Given a pointer to an array of bytes, returns a pointer to a value of the specified type
/// backed by those bytes, preserving pointer attributes.
pub fn bytesAsValue(comptime T: type, bytes: anytype) BytesAsValueReturnType(T, @TypeOf(bytes)) {
    return @ptrCast(bytes);
}

```

---

<div class="post-metadata">

**Author:** ![ericlang](https://ziggit.dev/user_avatar/ziggit.dev/ericlang/32/8515_2.png) [@ericlang](https://ziggit.dev/u/ericlang)\
**Post date:** [October 21, 2024, 8:08am UTC](https://ziggit.dev/t/move-bytes-to-extern-struct/6443/13 "2024-10-21T08:08:44Z")

</div>

yes i saw it in the zig sourcecode.

---

<div class="post-metadata">

**Author:** ![dee0xeed](https://ziggit.dev/letter_avatar_proxy/v4/letter/d/3ab097/32.png) [@dee0xeed](https://ziggit.dev/u/dee0xeed)\
**Post date:** [October 21, 2024, 10:12am UTC](https://ziggit.dev/t/move-bytes-to-extern-struct/6443/14 "2024-10-21T10:12:31Z")

</div>

`bytesToValue()` returns a copy (if I got it right), so if you really need to keep original data, use `bytesToValue()` (using my example):

```zig
    fn initFromBytes(d: []u8) S {
        var s: S = std.mem.bytesToValue(S, d);
        s.b = std.mem.bigToNative(u16, s.b);
        return s;
    }

```

Otherwise just

```zig
    fn initFromBytes(d: []u8) *S {
        const p: *S = std.mem.bytesAsValue(S, d);
        p.b = std.mem.bigToNative(u16, p.b);
        return p;
    }

```

---

<div class="post-metadata">

**Author:** ![geemili](https://ziggit.dev/user_avatar/ziggit.dev/geemili/32/1277_2.png) [@geemili](https://ziggit.dev/u/geemili)\
**Post date:** [October 22, 2024, 1:03am UTC](https://ziggit.dev/t/move-bytes-to-extern-struct/6443/15 "2024-10-22T01:03:27Z")

</div>

You might also consider [`std.mem.byteSwapAllFields`](https://github.com/ziglang/zig/blob/9f84f7f921d8a74926bb2f0ca1969b7b00f08172/lib/std/mem.zig#L2047-L2145) ([std library documentation](https://ziglang.org/documentation/master/std/#std.mem.byteSwapAllFields))

---

<div class="post-metadata">

**Author:** ![dee0xeed](https://ziggit.dev/letter_avatar_proxy/v4/letter/d/3ab097/32.png) [@dee0xeed](https://ziggit.dev/u/dee0xeed)\
**Post date:** [October 22, 2024, 7:09am UTC](https://ziggit.dev/t/move-bytes-to-extern-struct/6443/16 "2024-10-22T07:09:40Z")

</div>

```zig
const std = @import("std");

const S = extern struct {
    a: u8,
    b: u16 align(1), // supposed to be in BE byte order
    c: f32 align(1), // also BE

    fn initFromBytes(d: []u8) *S {
        const p: *S = std.mem.bytesAsValue(S, d);
        std.mem.byteSwapAllFields(S, p);
        return p;
    }
};

pub fn main() void {
    var d: [7]u8 = .{0x07, 0x00, 0x02, 0x40, 0x49, 0x0f, 0xd8};
    const p: *S = S.initFromBytes(&d);
    std.debug.print("{}\n", .{@sizeOf(S)});
    std.debug.print("{any}\n", .{p.*});
    // { .a = 7, .b = 2, .c = 3.141592e0 }
}

```

That’s really cool!
