#How to return an array (of the fixed size) from a slice?

1 messages · Page 1 of 1 (latest)

tidal pollen
#

I'm trying to implement a function that traverses over a single linked list and returns a string n:v -> n:v -> ...

I decided to use fixedBufferStream (actually I'm not sure why... probably because I don't know how to work with strings and "append" new bytes felt easier with the interface BufferStream provides). Anyway, as you can see in the code below, I added an ad-hoc [17]u8 in order to return fixed-length array as a value so that I can print it later on the caller site (the length is 17 because I know that the resulting string is 17 char long):

// returns n:v -> n:v -> ...
pub fn traverse(head: *Node) ![17]u8 {
    var curr = head;
    var buf: [512]u8 = undefined;
    var fbs = std.io.fixedBufferStream(&buf);
    while (true) {
        try fbs.writer().print("v:{} -> ", .{curr.v});
        if (curr.hasNext()) {
            curr = curr.getNext();
        } else {
            break;
        }
        if (curr == head) break;
    }
    try fbs.seekBy(-4); // removes trailing ' -> '
    // hack begins
    var ret: [17]u8 = undefined;
    std.mem.copy(u8, &ret, fbs.buffer[0..fbs.pos]);
    return ret;
    // this is what I was planning to use
    // return fbs.buffer[0..fbs.pos];
}

I thought that I could simply coerce fbs.buffer[0..fbs.pos] to the return type. However, after struggling with error messages and playing with @ptrCast, @as, etc. I ended up with (I think) unnecessary step of copying the contents of the buffer into a new array before returning it.

  1. Is there a way to remove the step of copying the buffer to array before returning it?
  2. Is there a better way of not using fixedBufferStream but just "raw" strings/arrays.
  3. (most probably no and yet I would like to ask a dumb question) Can I return an array as value with its length so that I can work with it after function's scope/stack/frame will be demolished?
#

Also, when I use return fbs.buffer[0..fbs.pos].*; which seems the right way to go, I get:

error: index syntax required for slice type '[]u8'
        return fbs.buffer[0..fbs.pos].*;

index syntax? It feels like I'm already using something related to indices.

trail root
#

if you know it's always going to be 17 chars long you can do fbs.buffer[0..17].*

#

this seemed to work for me

#

and for 3, arrays are values in zig, so you can save them without worrying about the underlying data being invalidated

#

also i would use a std.ArrayList(u8) for this tbh, unless you know the max upper bound is 512 and you dont want any allocations, it even exposes a writer interface

#

its best for your use case of "constructing a string"

tidal pollen
#

this seemed to work for me
Yes, for me too. Thank you. Right before posting I figured it out.

and yet.. what was that error: index syntax required for slice type '[]u8' thing? I'm really confused with this error message.

modest storm
#

fbs.pos isn't comptime-known

#

so fbs.buffer[0..fbs.pos] just returns []u8

#

erego, you're trying to dereference a slice

#

making it yell at you about dereferencing a slice, where you should be indexing into it

#

recommendation: return fbs.buffer[0..17].*;