#fmt without allocator

1 messages · Page 1 of 1 (latest)

barren spade
#
 pub fn fmt(self: *User) []const u8 {
        const buf: []u8 = undefined;
        const str = try std.fmt.bufPrint(buf, "age:{d} name:{s} job:{any}\n", .{ self.age, self.name, self.job });

        std.debug.print("buf:{s}\n", .{buf});
        std.debug.print("str:{s}\n", .{str});

        return buf;
    }
fmt-example.zig:11:21: error: expected type '[]const u8', found 'error{NoSpaceLeft}'
        const str = try std.fmt.bufPrint(buf, "age:{d} name:{s} job:{any}\n", .{ self.age, self.name, self.job });
forest saffron
#

you need either a heap allocator or to allocate your buffer on the stack

#

you can't just set it to undefined

#

also you need a try

#

and for the function to return an error union

proud lark
#

in the case of stack it would probably need to be from the code that calls this and pass it in as an arg

#

another option might be to return the buffer you pass into bufPrint from your fmt function as a sentinel terminated array instead of a slice and then use it as a slice from the calling function

#

if you use an allocator you would be transferring ownership of the memory, and I'm not sure how that would work if you allocated more memory for your buf than bufPrint returned and you returns just the return value from it from your function. That seems fraught, I guess would be simple to test with the GPA allocator to see if that leaks memory though

#

curious what others think, I have a couple of similar functions like this and wonder how other people do this

barren spade
#

so

barren spade
#
const User = struct {
    age: u8,
    name: []const u8,
    job: Job,
    allocator: std.mem.Allocator,

    pub fn fmt(
        self: *User,
    ) []const u8 {
        const format = "age: {d}, name: {s}, job:{any}\n";
        const buffer = try self.allocator.alloc(u8, @sizeOf(self));
        defer buffer;
        const args = .{ self.age, self.name, self.job };

        std.fmt.bufPrint(buffer, format, args);

        return buffer;
    }
};
#

i want something for auto fmt

proud lark
#

then let a buf be passed in as an arg the calling function would know you think?

barren spade
#

but idk the size of formatting

proud lark
#

I don't think @sizeOf makes sense there

barren spade
#

yup

#

so

#

what i could use?

proud lark
#

well I don't actually know if this make sense even if you knew the size

#

this doesn't compile

#

bufPrint returns a value

#

if you did _ = try std.fmt.bufPrint(buffer, format, args); and returned an error from fmt or used a catch there this would compile

barren spade
#

well

#

after the function

#

i have to free it after usage

#

that makes this operation pointless

proud lark
#

I just use an array

#

and return the array

#

I set it to some big reasonable size and that works for me

#

I also like having things know how to format themselves

abstract token
#

If you statically know the maximum size of the result, put that number in the brackets of the type of your buffer, so you get a stack-allocated array. Otherwise, you will need a heap allocator.

proud lark
#

bufPrint will return an NoSpaceLeft error if you don't have space also and you can handle it

abstract token
#

If you need to return the result, you will need to return the whole buffer (the slice would be a dangling reference), or take a reference to the target buffer in a parameter

proud lark
#

allocating heap for something this small just isn't a thing I would do personally

abstract token
gray vault
#

wonder if you could make a non-allocating fmt with iterators

compact lintel
#

id recommend implementing the format function of std.fmt.format, that will allow the user to choose whether to just print it or allocate it on the heap/stack. you need to have a function of the form

pub fn format(self: User, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
  try writer.print("age: {d}…", .{ self.age });
}
#

once you implement that you can use the struct in anything that uses format, ie all writers