diff --git a/src/user.zig b/src/user.zig index 2bacbdb..a73c540 100644 --- a/src/user.zig +++ b/src/user.zig @@ -8,12 +8,13 @@ const assert = std.debug.assert; const mem = std.mem; const Allocator = mem.Allocator; const ArrayList = std.ArrayList; + // Idx2ShellProto is a function prototype that, given a shell's index (in // global shell section), will return a shell string. Matches ShellReader.get. const Idx2ShellProto = fn (u6) []const u8; // User is a convenient public struct for record construction and -// serialization. Iterator can help retrieve these records. +// serialization. pub const User = struct { uid: u32, gid: u32, @@ -23,7 +24,10 @@ pub const User = struct { shell: []const u8, // deep-clones a User record with a given Allocator. - pub fn clone(self: *const User, allocator: Allocator) Allocator.Error!User { + pub fn clone( + self: *const User, + allocator: Allocator, + ) Allocator.Error!User { const stringdata = try allocator.alloc(u8, self.strlen()); const gecos_start = self.name.len; const home_start = gecos_start + self.gecos.len; @@ -133,8 +137,9 @@ fn packedUser(immutable: bool) type { const Bytes = if (immutable) []const u8 else []u8; const InnerPointer = if (immutable) *const Inner else *Inner; - // PackedUser does not allocate; it re-interprets the "bytes" blob field. - // Both of those fields are pointers to "our representation" of that field. + // PackedUser does not allocate; it re-interprets the "bytes" blob + // field. Both of those fields are pointers to "our representation" of + // that field. inner: InnerPointer, userdata: Bytes, @@ -190,9 +195,9 @@ fn packedUser(immutable: bool) type { }; } - // packTo packs the User record and copies it to the given byte slice. The - // slice must have at least maxRecordSize() bytes available. - // The slice is passed as a pointer, so it can be mutated. + // packTo packs the User record and copies it to the given byte slice. + // The slice must have at least maxRecordSize() bytes available. The + // slice is passed as a pointer, so it can be mutated. const packErr = InvalidRecord || Allocator.Error; pub fn packTo( arr: *ArrayList(u8), @@ -291,11 +296,8 @@ fn packedUser(immutable: bool) type { return idxFn(self.inner.shell_len_or_idx); } + // mutable only: this function will refuse to compile otherwise. pub fn setAdditionalGidsOffset(self: Self, new: u29) void { - // TODO(motiejus) how to not declare function for const PackedUser at all? - if (immutable) { - @compileError("this function is available only for mutable PackedUsers"); - } self.inner.additional_gids_offset = new; } }; @@ -310,7 +312,11 @@ test "PackedUser internal and external alignment" { // cannot be converted from/to [@bitSizeOf(PackedUser)/8]u8; // asBytes/bytesAsValue use @sizeOf, which is larger. Now we are putting no // more than 1, but it probably could be higher. - try testing.expectEqual(8, @sizeOf(PackedUserConst.Inner) * 8 - @bitSizeOf(PackedUserConst.Inner)); + try testing.expectEqual( + 8, + @sizeOf(PackedUserConst.Inner) * 8 - + @bitSizeOf(PackedUserConst.Inner), + ); } fn testShellIndex(shell: []const u8) ?u6 { @@ -368,48 +374,45 @@ test "construct PackedUser section" { } var i: u29 = 0; - { - var it = PackedUserConst.iterator(buf.items, testShell); - while (it.next()) |user| : (i += 1) { - try testing.expectEqual(users[i].uid, user.uid()); - try testing.expectEqual(users[i].gid, user.gid()); - try testing.expectEqual( - @as(u29, std.math.maxInt(u29)), - user.additionalGidsOffset(), - ); - try testing.expectEqualStrings(users[i].name, user.name()); - try testing.expectEqualStrings(users[i].gecos, user.gecos()); - try testing.expectEqualStrings(users[i].home, user.home()); - try testing.expectEqualStrings(users[i].shell, user.shell(testShell)); - } - try testing.expectEqual(users.len, i); + var it1 = PackedUserConst.iterator(buf.items, testShell); + while (it1.next()) |user| : (i += 1) { + try testing.expectEqual(users[i].uid, user.uid()); + try testing.expectEqual(users[i].gid, user.gid()); + try testing.expectEqual( + @as(u29, std.math.maxInt(u29)), + user.additionalGidsOffset(), + ); + try testing.expectEqualStrings(users[i].name, user.name()); + try testing.expectEqualStrings(users[i].gecos, user.gecos()); + try testing.expectEqualStrings(users[i].home, user.home()); + try testing.expectEqualStrings(users[i].shell, user.shell(testShell)); } + try testing.expectEqual(users.len, i); - { - var it = PackedUserMut.iterator(buf.items, testShell); - i = 0; - while (it.next()) |user| : (i += 1) { - user.setAdditionalGidsOffset(i); - } - try testing.expectEqual(users.len, i); + var it2 = PackedUserMut.iterator(buf.items, testShell); + i = 0; + while (it2.next()) |user| : (i += 1) { + user.setAdditionalGidsOffset(i); } + try testing.expectEqual(users.len, i); - { - var it = PackedUserConst.iterator(buf.items, testShell); - i = 0; - while (it.next()) |user| : (i += 1) { - try testing.expectEqual(users[i].gid, user.gid()); - try testing.expectEqual(i, user.additionalGidsOffset()); - try testing.expectEqualStrings(users[i].name, user.name()); - } - try testing.expectEqual(users.len, i); + var it3 = PackedUserConst.iterator(buf.items, testShell); + i = 0; + while (it3.next()) |user| : (i += 1) { + try testing.expectEqual(users[i].gid, user.gid()); + try testing.expectEqual(i, user.additionalGidsOffset()); + try testing.expectEqualStrings(users[i].name, user.name()); } + try testing.expectEqual(users.len, i); } test "PackedUser.maxSize()" { // TODO(motiejus) try using a slice that points to an array in stack. // As of writing, I am getting a stack smashing error. - var buf = try ArrayList(u8).initCapacity(testing.allocator, PackedUserConst.maxSize()); + var buf = try ArrayList(u8).initCapacity( + testing.allocator, + PackedUserConst.maxSize(), + ); defer buf.deinit(); const largeUser = User{