From d6ba7bed6321f730e84203e29cbd483f86a55921 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Motiejus=20Jak=C5=A1tys?= Date: Wed, 9 Mar 2022 07:06:39 +0200 Subject: [PATCH] group_members --- src/sections.zig | 70 ++++++++++++++++++++++++++++-------------------- src/user.zig | 8 ++---- 2 files changed, 43 insertions(+), 35 deletions(-) diff --git a/src/sections.zig b/src/sections.zig index 4b3c349..dd02817 100644 --- a/src/sections.zig +++ b/src/sections.zig @@ -102,17 +102,14 @@ const Corpus = struct { members.len += 1; members[members.len - 1] = user_idx; try user2groups[user_idx].append(allocator, @intCast(u32, i)); - } else { - return error.NotFound; - } + } else return error.NotFound; } group2users[i] = members; } - for (group2users) |*groupusers| { + for (group2users) |*groupusers| sort.sort(u32, groupusers.*, {}, comptime sort.asc(u32)); - } var user2groups_final = try allocator.alloc([]const u32, users.len); user2groups_final.len = users.len; @@ -270,6 +267,7 @@ pub fn usersSection( pub const GroupMembers = struct { // group index to it's offset in blob idx2offset: []const u64, + // members are delta-varint encoded byte-offsets to the user struct blob: []const u8, pub fn deinit(self: *GroupMembers, allocator: Allocator) void { @@ -291,8 +289,8 @@ pub fn groupMembers( // zero'th entry is empty, so empty groups can refer to it try compress.appendUvarint(&blob, 0); - var scratch = try allocator.alloc(u32, 256); - defer allocator.free(scratch); + var scratch = try ArrayList(u32).initCapacity(allocator, 1024); + defer scratch.deinit(); for (corpus.group2users) |members, group_idx| { if (members.len == 0) { @@ -300,16 +298,18 @@ pub fn groupMembers( continue; } - scratch = try allocator.realloc(scratch, members.len); - scratch.len = members.len; - mem.copy(u32, scratch, members); + idx2offset[group_idx] = blob.items.len; + try scratch.ensureTotalCapacity(members.len); + scratch.items.len = members.len; + for (members) |user_idx, i| + scratch.items[i] = user2offset[user_idx]; - compress.deltaCompress(u32, scratch) catch |err| switch (err) { + compress.deltaCompress(u32, scratch.items) catch |err| switch (err) { error.NotSorted => unreachable, }; try compress.appendUvarint(&blob, members.len); - for (scratch) |user_idx| - try compress.appendUvarint(&blob, user2offset[user_idx]); + for (scratch.items) |elem| + try compress.appendUvarint(&blob, elem); } return GroupMembers{ .idx2offset = idx2offset, @@ -325,9 +325,7 @@ fn cmpUser(_: void, a: User, b: User) bool { if (utf8_b.nextCodepoint()) |codepoint_b| { if (codepoint_a == codepoint_b) { continue; - } else { - return codepoint_a < codepoint_b; - } + } else return codepoint_a < codepoint_b; } // a is a prefix of b. It is thus shorter. @@ -373,11 +371,11 @@ pub const AllSections = struct { &user_gids, &shell_sections, ); - //const group_members = try groupMembers( - // allocator, - // corpus, - // users.idx2offset, - //); + const group_members = try groupMembers( + allocator, + corpus, + users.idx2offset, + ); return AllSections{ .allocator = allocator, .bdz_gid = bdz_gid, @@ -389,8 +387,7 @@ pub const AllSections = struct { .shell_blob = mem.sliceAsBytes(shell_blob.constSlice()), .user_gids = user_gids, .users = users, - //.group_members = group_members, - .group_members = undefined, + .group_members = group_members, }; } @@ -402,6 +399,7 @@ pub const AllSections = struct { self.shell_sections.deinit(); self.user_gids.deinit(self.allocator); self.users.deinit(self.allocator); + self.group_members.deinit(self.allocator); self.* = undefined; } }; @@ -512,13 +510,26 @@ test "test corpus" { try testing.expectEqual(groupsOfVidmantas[2], g_all); } -test "test sections" { +test "test group members" { const allocator = testing.allocator; var corpus = try testCorpus(allocator); defer corpus.deinit(); - var all = try AllSections.init(allocator, &corpus); - defer all.deinit(); + var sections = try AllSections.init(allocator, &corpus); + defer sections.deinit(); + + const blob = sections.group_members.blob; + var group_idx: usize = 0; + while (group_idx < corpus.groups.len) : (group_idx += 1) { + const offset = sections.group_members.idx2offset[group_idx]; + var vit = try compress.VarintSliceIterator(blob[offset..]); + var it = compress.DeltaDecompressionIterator(&vit); + for (corpus.group2users[group_idx]) |user_idx| { + const got_user_offset = (try it.next()).?; + const want_user_offset = sections.users.idx2offset[user_idx]; + try testing.expectEqual(got_user_offset, want_user_offset); + } + } } test "userGids" { @@ -529,9 +540,10 @@ test "userGids" { var user_gids = try userGids(allocator, &corpus); defer user_gids.deinit(allocator); - for (corpus.users) |_, userIdx| { - const groups = corpus.user2groups[userIdx]; - const offset = user_gids.idx2offset[userIdx]; + var user_idx: usize = 0; + while (user_idx < corpus.users.len) : (user_idx += 1) { + const groups = corpus.user2groups[user_idx]; + const offset = user_gids.idx2offset[user_idx]; if (groups.len == 0) { try testing.expect(offset == 0); continue; diff --git a/src/user.zig b/src/user.zig index ea1f68b..f94370e 100644 --- a/src/user.zig +++ b/src/user.zig @@ -105,9 +105,7 @@ fn packedUser(comptime ShellIndexType: type) type { const name_len = self.nameLen(); if (self.name_is_a_suffix) { return self.homeLen() - name_len; - } else { - return self.homeLen(); - } + } else return self.homeLen(); } fn nameLen(self: *const Inner) usize { @@ -117,9 +115,7 @@ fn packedUser(comptime ShellIndexType: type) type { fn gecosStart(self: *const Inner) usize { if (self.name_is_a_suffix) { return self.homeLen(); - } else { - return self.homeLen() + self.nameLen(); - } + } else return self.homeLen() + self.nameLen(); } fn gecosLen(self: *const Inner) usize {