Search code examples
zig

Should a function return []const u8 or []u8 if the caller owns the slice


I noticed that a library I'm using frequently returns []const u8 instead of []u8 when it allocates memory and the caller is responsible for freeing it.

Should a function return a mutable slice []u8 when the data is owned by the caller and must be freed?

Example

fn prefixString(
    allocator: std.mem.Allocator,
    string: []const u8,
    prefix: []const u8
) ![]u8 {
    return std.mem.concat(allocator, u8, &[_][]const u8{ prefix, string });
}

Here, prefixString returns a mutable slice of bytes, just like its underlying function, std.mem.concat.


Solution

  • While it can be argued that it all depends on the design decisions of the library developers, it's indeed better to return []T instead of []const T when the caller owns the memory and needs to free it.

    The const provides a way to express restrictions in the API, that can protect against certain errors.

    But in this case, the restriction isn't real, and the library users may have to cast away the const to archive their goals.