1
Fork 0

username2groups -> user2groups

main
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),
name2group: StringHashMap(u32),
group2users: []const []const u32,
username2groups: StringHashMap([]u32),
user2groups: []const []const u32,
pub fn init(
baseAllocator: Allocator,
@ -88,10 +88,9 @@ const Corpus = struct {
// uses baseAllocator, because it will be freed before
// returning from this function. This keeps the arena clean.
var username2groups = StringHashMap(
ArrayListUnmanaged(u32),
).init(baseAllocator);
defer username2groups.deinit();
var user2groups = try baseAllocator.alloc(ArrayListUnmanaged(u32), users.len);
defer baseAllocator.free(user2groups);
mem.set(ArrayListUnmanaged(u32), user2groups, ArrayListUnmanaged(u32){});
for (groups) |*group, i| {
var members = try allocator.alloc(u32, group.members.count());
@ -99,36 +98,27 @@ const Corpus = struct {
var it = group.members.iterator();
while (it.next()) |memberName| {
if (name2user.get(memberName.*)) |idx| {
if (name2user.get(memberName.*)) |user_idx| {
members.len += 1;
members[members.len - 1] = idx;
members[members.len - 1] = user_idx;
try user2groups[user_idx].append(allocator, @intCast(u32, i));
} else {
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;
}
for (group2users) |*groupUsers| {
sort.sort(u32, groupUsers.*, {}, comptime sort.asc(u32));
for (group2users) |*groupusers| {
sort.sort(u32, groupusers.*, {}, comptime sort.asc(u32));
}
var it2 = username2groups.valueIterator();
while (it2.next()) |userGroups|
sort.sort(u32, userGroups.items, {}, comptime sort.asc(u32));
var username2groups_final = StringHashMap([]u32).init(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);
var user2groups_final = try allocator.alloc([]const u32, users.len);
user2groups_final.len = users.len;
for (user2groups) |*usergroups, i| {
sort.sort(u32, usergroups.items, {}, comptime sort.asc(u32));
user2groups_final[i] = usergroups.toOwnedSlice(allocator);
}
return Corpus{
@ -140,7 +130,7 @@ const Corpus = struct {
.name2user = name2user,
.name2group = name2group,
.group2users = group2users,
.username2groups = username2groups_final,
.user2groups = user2groups_final,
};
}
@ -216,23 +206,24 @@ pub fn userGids(
var scratch = try allocator.alloc(u32, 256);
defer allocator.free(scratch);
for (corpus.users) |user, user_idx| {
if (corpus.username2groups.get(user.name)) |usergroups| {
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);
} else {
for (corpus.users) |_, user_idx| {
const usergroups = corpus.user2groups[user_idx];
if (usergroups.len == 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{
@ -510,12 +501,10 @@ test "test corpus" {
try testing.expectEqual(membersOfAll[1], svc_bar);
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[1], g_vidmantas);
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" {
@ -535,19 +524,19 @@ test "userGids" {
var user_gids = try userGids(allocator, &corpus);
defer user_gids.deinit(allocator);
for (corpus.users) |user, userIdx| {
const groups = corpus.username2groups.get(user.name);
for (corpus.users) |_, userIdx| {
const groups = corpus.user2groups[userIdx];
const offset = user_gids.idx2offset[userIdx];
if (groups == null) {
if (groups.len == 0) {
try testing.expect(offset == 0);
continue;
}
var vit = try compress.VarintSliceIterator(user_gids.blob[offset..]);
var it = compress.DeltaDecompressionIterator(&vit);
try testing.expectEqual(it.remaining(), groups.?.len);
try testing.expectEqual(it.remaining(), groups.len);
var i: u64 = 0;
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);
}
}
}