const std = @import("std"); const mem = std.mem; const Allocator = mem.Allocator; const ArrayList = std.ArrayList; const maxInt = std.math.maxInt; const User = @This(); uid: u32, gid: u32, name: []const u8, gecos: []const u8, home: []const u8, shell: []const u8, // deep-clones a User record with a given Allocator. pub fn clone( self: *const User, allocator: Allocator, ) error{OutOfMemory}!User { const stringdata = try allocator.alloc(u8, self.strlen()); const gecos_start = self.name.len; const home_start = gecos_start + self.gecos.len; const shell_start = home_start + self.home.len; mem.copy(u8, stringdata[0..self.name.len], self.name); mem.copy(u8, stringdata[gecos_start..], self.gecos); mem.copy(u8, stringdata[home_start..], self.home); mem.copy(u8, stringdata[shell_start..], self.shell); return User{ .uid = self.uid, .gid = self.gid, .name = stringdata[0..self.name.len], .gecos = stringdata[gecos_start .. gecos_start + self.gecos.len], .home = stringdata[home_start .. home_start + self.home.len], .shell = stringdata[shell_start .. shell_start + self.shell.len], }; } fn strlen(self: *const User) usize { return self.name.len + self.gecos.len + self.home.len + self.shell.len; } pub fn deinit(self: *User, allocator: Allocator) void { const slice = self.home.ptr[0..self.strlen()]; allocator.free(slice); self.* = undefined; } pub fn fromReader(allocator: Allocator, reader: anytype) ![]User { var users = ArrayList(User).init(allocator); var scratch = ArrayList(u8).init(allocator); defer scratch.deinit(); while (true) { const line = reader.readUntilDelimiterArrayList(&scratch, '\n', maxInt(usize)); _ = line; } _ = users; } const testing = std.testing; test "User.clone" { var allocator = testing.allocator; const user = User{ .uid = 1000, .gid = 1000, .name = "vidmantas", .gecos = "Vidmantas Kaminskas", .home = "/home/vidmantas", .shell = "/bin/bash", }; var user2 = try user.clone(allocator); defer user2.deinit(allocator); try testing.expectEqualStrings(user.shell, "/bin/bash"); }