1
Fork 0

username2groups -> user2groups

This commit is contained in:
Motiejus Jakštys 2022-03-09 05:54:00 +02:00 committed by Motiejus Jakštys
parent c79741f4e2
commit 15e018389a
1 changed files with 37 additions and 48 deletions

View File

@ -38,7 +38,7 @@ const Corpus = struct {
name2user: StringHashMap(u32), name2user: StringHashMap(u32),
name2group: StringHashMap(u32), name2group: StringHashMap(u32),
group2users: []const []const u32, group2users: []const []const u32,
username2groups: StringHashMap([]u32), user2groups: []const []const u32,
pub fn init( pub fn init(
baseAllocator: Allocator, baseAllocator: Allocator,
@ -88,10 +88,9 @@ const Corpus = struct {
// uses baseAllocator, because it will be freed before // uses baseAllocator, because it will be freed before
// returning from this function. This keeps the arena clean. // returning from this function. This keeps the arena clean.
var username2groups = StringHashMap( var user2groups = try baseAllocator.alloc(ArrayListUnmanaged(u32), users.len);
ArrayListUnmanaged(u32), defer baseAllocator.free(user2groups);
).init(baseAllocator); mem.set(ArrayListUnmanaged(u32), user2groups, ArrayListUnmanaged(u32){});
defer username2groups.deinit();
for (groups) |*group, i| { for (groups) |*group, i| {
var members = try allocator.alloc(u32, group.members.count()); var members = try allocator.alloc(u32, group.members.count());
@ -99,36 +98,27 @@ const Corpus = struct {
var it = group.members.iterator(); var it = group.members.iterator();
while (it.next()) |memberName| { while (it.next()) |memberName| {
if (name2user.get(memberName.*)) |idx| { if (name2user.get(memberName.*)) |user_idx| {
members.len += 1; members.len += 1;
members[members.len - 1] = idx; members[members.len - 1] = user_idx;
try user2groups[user_idx].append(allocator, @intCast(u32, i));
} else { } else {
return error.NotFound; return error.NotFound;
} }
var groupsOfMember = try username2groups.getOrPut(memberName.*);
if (!groupsOfMember.found_existing)
groupsOfMember.value_ptr.* = ArrayListUnmanaged(u32){};
try groupsOfMember.value_ptr.*.append(allocator, @intCast(u32, i));
} }
group2users[i] = members; group2users[i] = members;
} }
for (group2users) |*groupUsers| { for (group2users) |*groupusers| {
sort.sort(u32, groupUsers.*, {}, comptime sort.asc(u32)); sort.sort(u32, groupusers.*, {}, comptime sort.asc(u32));
} }
var it2 = username2groups.valueIterator(); var user2groups_final = try allocator.alloc([]const u32, users.len);
while (it2.next()) |userGroups| user2groups_final.len = users.len;
sort.sort(u32, userGroups.items, {}, comptime sort.asc(u32)); for (user2groups) |*usergroups, i| {
sort.sort(u32, usergroups.items, {}, comptime sort.asc(u32));
var username2groups_final = StringHashMap([]u32).init(allocator); user2groups_final[i] = usergroups.toOwnedSlice(allocator);
var it = username2groups.iterator();
while (it.next()) |elem| {
const username = elem.key_ptr.*;
const usergroups = elem.value_ptr.*.toOwnedSlice(allocator);
try username2groups_final.put(username, usergroups);
} }
return Corpus{ return Corpus{
@ -140,7 +130,7 @@ const Corpus = struct {
.name2user = name2user, .name2user = name2user,
.name2group = name2group, .name2group = name2group,
.group2users = group2users, .group2users = group2users,
.username2groups = username2groups_final, .user2groups = user2groups_final,
}; };
} }
@ -216,23 +206,24 @@ pub fn userGids(
var scratch = try allocator.alloc(u32, 256); var scratch = try allocator.alloc(u32, 256);
defer allocator.free(scratch); defer allocator.free(scratch);
for (corpus.users) |user, user_idx| { for (corpus.users) |_, user_idx| {
if (corpus.username2groups.get(user.name)) |usergroups| { const usergroups = corpus.user2groups[user_idx];
idx2offset[user_idx] = blob.items.len; if (usergroups.len == 0) {
scratch = try allocator.realloc(scratch, usergroups.len);
scratch.len = usergroups.len;
for (usergroups) |group_idx, i|
scratch[i] = corpus.groups[group_idx].gid;
compress.deltaCompress(u32, scratch) catch |err| switch (err) {
error.NotSorted => unreachable,
};
try compress.appendUvarint(&blob, usergroups.len);
for (scratch) |gid|
try compress.appendUvarint(&blob, gid);
try pad.arrayList(&blob, userGidsPaddingBits);
} else {
idx2offset[user_idx] = 0; idx2offset[user_idx] = 0;
continue;
} }
idx2offset[user_idx] = blob.items.len;
scratch = try allocator.realloc(scratch, usergroups.len);
scratch.len = usergroups.len;
for (usergroups) |group_idx, i|
scratch[i] = corpus.groups[group_idx].gid;
compress.deltaCompress(u32, scratch) catch |err| switch (err) {
error.NotSorted => unreachable,
};
try compress.appendUvarint(&blob, usergroups.len);
for (scratch) |gid|
try compress.appendUvarint(&blob, gid);
try pad.arrayList(&blob, userGidsPaddingBits);
} }
return UserGids{ return UserGids{
@ -510,12 +501,10 @@ test "test corpus" {
try testing.expectEqual(membersOfAll[1], svc_bar); try testing.expectEqual(membersOfAll[1], svc_bar);
try testing.expectEqual(membersOfAll[2], vidmantas); try testing.expectEqual(membersOfAll[2], vidmantas);
const groupsOfVidmantas = corpus.username2groups.get("vidmantas").?; const groupsOfVidmantas = corpus.user2groups[vidmantas];
try testing.expectEqual(groupsOfVidmantas[0], g_service_account); try testing.expectEqual(groupsOfVidmantas[0], g_service_account);
try testing.expectEqual(groupsOfVidmantas[1], g_vidmantas); try testing.expectEqual(groupsOfVidmantas[1], g_vidmantas);
try testing.expectEqual(groupsOfVidmantas[2], g_all); try testing.expectEqual(groupsOfVidmantas[2], g_all);
try testing.expectEqual(corpus.username2groups.get("nobody"), null);
try testing.expectEqual(corpus.username2groups.get("doesnotexist"), null);
} }
test "test sections" { test "test sections" {
@ -535,19 +524,19 @@ test "userGids" {
var user_gids = try userGids(allocator, &corpus); var user_gids = try userGids(allocator, &corpus);
defer user_gids.deinit(allocator); defer user_gids.deinit(allocator);
for (corpus.users) |user, userIdx| { for (corpus.users) |_, userIdx| {
const groups = corpus.username2groups.get(user.name); const groups = corpus.user2groups[userIdx];
const offset = user_gids.idx2offset[userIdx]; const offset = user_gids.idx2offset[userIdx];
if (groups == null) { if (groups.len == 0) {
try testing.expect(offset == 0); try testing.expect(offset == 0);
continue; continue;
} }
var vit = try compress.VarintSliceIterator(user_gids.blob[offset..]); var vit = try compress.VarintSliceIterator(user_gids.blob[offset..]);
var it = compress.DeltaDecompressionIterator(&vit); var it = compress.DeltaDecompressionIterator(&vit);
try testing.expectEqual(it.remaining(), groups.?.len); try testing.expectEqual(it.remaining(), groups.len);
var i: u64 = 0; var i: u64 = 0;
while (try it.next()) |gid| : (i += 1) { while (try it.next()) |gid| : (i += 1) {
try testing.expectEqual(gid, corpus.groups[groups.?[i]].gid); try testing.expectEqual(gid, corpus.groups[groups[i]].gid);
} }
} }
} }