const std = @import("std");

pub const StringBuilder = struct {
    list: std.ArrayList(u8),
    
    pub fn init(allocator: std.mem.Allocator) StringBuilder {
        return StringBuilder{
            .list = std.ArrayList(u8).init(allocator),
        };
    }
    
    pub fn initWithCapacity(allocator: std.mem.Allocator, capacity: usize) StringBuilder {
        var sb = StringBuilder{
            .list = std.ArrayList(u8).init(allocator),
        };
        sb.list.ensureTotalCapacity(capacity) catch {};
        return sb;
    }
    
    pub fn append(self: *StringBuilder, str: []const u8) !void {
        try self.list.appendSlice(str);
    }
    
    pub fn appendChar(self: *StringBuilder, c: u8) !void {
        try self.list.append(c);
    }
    
    pub fn appendFormat(self: *StringBuilder, comptime fmt: []const u8, args: anytype) !void {
        try std.fmt.format(self.list.writer(), fmt, args);
    }
    
    pub fn appendLine(self: *StringBuilder, str: []const u8) !void {
        try self.append(str);
        try self.appendChar('\n');
    }
    
    pub fn build(self: *StringBuilder) ![]u8 {
        return try self.list.toOwnedSlice();
    }
    
    pub fn deinit(self: *StringBuilder) void {
        self.list.deinit();
    }
    
    pub fn len(self: *const StringBuilder) usize {
        return self.list.items.len;
    }
    
    pub fn clear(self: *StringBuilder) void {
        self.list.clearAndFree();
    }
};