[HN Gopher] Resizable Structs in Zig
___________________________________________________________________
Resizable Structs in Zig
Author : rvrb
Score : 29 points
Date : 2025-07-26 21:43 UTC (1 hours ago)
(HTM) web link (tristanpemble.com)
(TXT) w3m dump (tristanpemble.com)
| rvrb wrote:
| I am the author of this post, let me know if you have any
| questions or feedback :)
| 90s_dev wrote:
| Ok I will.
| atmikemikeb wrote:
| I thought about dynamically sized types (DSTs) in zig recently.
| Was considering writing about it. I came to a different
| conclusion. Why not use zig's opaque?
|
| It's pretty clean at this imo: Less metaprogramming but I think
| nicer to use in some cases. const Connection =
| opaque { pub const Header = struct { host_len:
| usize, // add more static fields or dynamic field
| lengths here //buff_len: usize, };
| pub fn init(a: std.mem.Allocator, args: struct { host: []const u8
| }) *@This() { var this = a.allocWithOptions(u8,
| @sizeOf(Header) + host.len, @alignOf(Header), null);
| @memcpy(this[@sizeOf(Header)..], host); return
| this.ptr; } pub fn host(self: *const
| @This()) []const u8 { const bytes: *u8 =
| @ptrCast(self); const header: *Header = @ptrCast(self);
| const data = bytes[@sizeOf(Header)..]; const host =
| data[0..header.host_len]; return host; }
| };
|
| going off memory so I expect it to not actually compile, but I've
| definitely done something like this before.
| rvrb wrote:
| I would describe this approach as 'intrusive' - you're storing
| the lengths of the arrays behind the pointer, enforcing a
| certain layout of the memory being allocated.
|
| Because the solution outlined in the article stores the lengths
| alongside the pointer, instead of behind it, there is room for
| it to work across an ABI (though it currently does not). It's
| more like a slice in this way.
|
| You could in theory implement your opaque approach using this
| as a utility to avoid the headache of alignment calculations.
| For this reason, I think that makes the approach outlined in
| the article more suitable as a candidate for inclusion in the
| standard library.
| atmikemikeb wrote:
| Yeah I think mine is more about being able to provide a
| `host()` helper function instead of a `.get(.host)` meta
| function. It is somewhat boilerplate-y. I think it's really a
| matter of taste haha. Likely yours would be useful regardless
| if this is done a lot, since it abstracts some of it, if one
| wants that.
| mananaysiempre wrote:
| > Zig does not, and will not, have VLAs in the language spec.
| Instead, you can allocate a slice on the heap. If you want to
| have the data on the stack, use an array as a bounded backing
| store, and work with a slice into it[.]
|
| Too bad, aligned byte-typed VLAs (and a license to retype them as
| a struct) is what you need to get stack allocation across ABI
| boundaries the way Swift does it. (A long long time ago, SOM,
| IBM's answer to Microsoft's COM, did this in C with alloca
| instead of VLAs, but that's the same thing.) I guess I'll have to
| use something else instead.
| rvrb wrote:
| I think there may be room to expand this implementation to
| support such a use case. Right now it enforces an `.auto`
| layout of the struct provided in order to ensure alignment, but
| its easy to imagine supporting an `extern struct` with a
| defined layout.
|
| Conceivably, an implementation of this `ResizableStruct` that
| uses an array buffer as backing rather than a heap allocation,
| and supports the defined layout of an extern struct, could be
| used to work across the ABI
___________________________________________________________________
(page generated 2025-07-26 23:00 UTC)