[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)